Lỗi adding permission khi thực hiện hàm importrange

Google Sheets là công cụ tuyệt vời để lưu trữ bảng tính trực tuyến, bạn có thể truy cập bảng tính bất kỳ lúc nào ở bất kỳ đâu và luôn sẵn sàng để chia sẻ với người khác.

Nếu bạn chỉ muốn chia sẻ một phần của bảng tính, tạo một sheet mới và dùng hàm



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

0 có thể đã đáp ứng yêu cầu của bạn. Tuy nhiên, nếu bạn muốn cung cấp một giao diện trực quan hơn cho người dùng để thực hiện các thao tác như sort, search, highlight, paging... thì bạn có thể viết web app sử dụng Apps Script của Google cung cấp.

Bài này gồm 2 phần. Phần 1 chúng ta sẽ hiển thị toàn bộ dữ liệu mỗi khi load web app. Phần 2 chúng ta sẽ tạo chức năng Search và chỉ hiển thị đúng dữ liệu mà người dùng yêu cầu. Lưu ý, bài này dành cho beginner.

1. Hiển thị data table

Để tạo table, chúng ta có thể sử dụng JavaScript thuần, nhưng mình sử dụng Data Tables jQuery plug-in để việc tạo table dễ dàng hơn và có sẵn nhiều chức năng.

Mình tìm table jQuery plug-in trên Google và thấy plug-in này hiện ra đầu tiên nên dùng luôn. Nếu bạn biết plug-in nào hay ho hơn thì hãy cho mình biết nhé.

Chúng ta cùng xem qua thành quả trước khi bắt tay vào viết code. Data Table jQuery plug-in to render table.

1 hoặc



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

2 có trả về HTML Service object để tạo giao diện cho web app. Chúng ta tách file CSS, JavaScript với file HTML theo hướng dẫn của Google bằng hàm



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

3.

// file Code.gs
function doGet[e] {
  return HtmlService.createTemplateFromFile['Index.html']
    .evaluate[];
}
function include[filename] {
  return HtmlService.createHtmlOutputFromFile[filename]
    .getContent[];
}

Index.html

Trong file HTML, chúng ta sẽ tạo thẻ



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

4 với



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

5 để render table sau khi lấy dữ liệu từ file Google Sheets. Các bạn lưu ý, Data Tables jQuery là 1 plug-in của jQuery nên đừng quên chèn link CDN jQuery vào file HTML trước khi chèn link plug-in.

Bây giờ mình đã biết chèn link file JavaScript cũng phải đúng thứ tự thì code máy chạy. Hồi đó tự học nên không có ai dạy về điều này hết.



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

Code JavaScript

Chúng ta dùng hàm ready của jQuery để thực thi một hàm callback khi DOM đã sẵn sàng. Chúng ta sẽ sử dụng class google.script.run để chạy hàm Apps Script khi ở client-side.

Để khởi tạo DataTable instance thì chúng ta cần truyền vào



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

6,



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

7 và một số option khác các bạn có thể tham khảo tại //datatables.net/.

// File JavaScript.html

  $[].ready[function[]{
    google.script.run.withSuccessHandler[showDataTable]
      .getAllData[];
  }];
  function showDataTable[dataTable] {
    var header = [];
    dataTable.header.forEach[item => {
       header.push[{title: item}];
    }]
    $['
# table'].DataTable[{
      data: dataTable.data,
      columns: header,
      searching: false,
      info: false
    }]
  }

Code server- side

Ở server-side [file Code.gs] chúng ta sẽ viết hàm



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

8 để trả về dữ liệu để tạo bảng.

// File Code.gs
var ss = SpreadsheetApp.getActiveSpreadsheet[];
var sheet = ss.getSheetByName['Invoice'];
function doGet[e] {
    ...
}
function include[filename] {
    ...
}
function getAllData[] {
  var range = sheet.getRange[2, 1, sheet.getLastRow[]-1, sheet.getLastColumn[]];
  var values = range.getValues[];
  return {
    header: getHeaderArr[],
    data: values
  }
}
function getHeaderArr[] {
  var headerRowPosition = 1; 
  var range = sheet.getRange[headerRowPosition, 1, 1, sheet.getLastColumn[]];
  return range.getValues[][0];
}

Thêm loader

Mỗi lần load dữ liệu có thể mất vài giây nên chúng ta sẽ thêm loader để báo hiệu cho người dùng biết là dữ liệu đang được load.


...
...

Chúng ta sẽ tạo một vùng có id là



  
    
    
    
  
  
    

Invoice

Invoice data from the spreadsheet, use Data Table jQuery plug-in to render table.

9 để chèn loader. Code CSS được tham khảo từ website //www.w3schools.com/.



  
# loading {
    margin: auto;
    border: 16px solid 
# f3f3f3;
    border-radius: 50%;
    border-top: 16px solid 
# 3498db;
    width: 120px;
    height: 120px;
    -webkit-animation: spin 2s linear infinite; /* Safari */
    animation: spin 2s linear infinite;
  }
  /* Safari */
  @-webkit-keyframes spin {
    0% { -webkit-transform: rotate[0deg]; }
    100% { -webkit-transform: rotate[360deg]; }
  }
  @keyframes spin {
    0% { transform: rotate[0deg]; }
    100% { transform: rotate[360deg]; }
  }

Chúng ta sẽ ẩn loader này đi khi dữ liệu đã được tải xong.

  function showDataTable[dataTable] {
    $['
# loading'].hide[];
    ...
}

Kết quả

Như vậy chúng ta đã lấy được dữ liệu từ Google Sheets và tạo table trên web app sử dụng Data Table jQuery plug-in.

2. Chức năng Search

Data Tables jQuery plug-in cũng có chức năng search build-in. Tuy nhiên, để search thì cần phải fetch toàn bộ data giống như phần 1 ở trên. Trong nhiều trường hợp, chúng ta không muốn công khai toàn bộ dữ liệu mà chỉ muốn người dùng search tìm đúng thông tin của họ. Chẳng hạn:

Chúng ta sẽ viết lại web và chỉ hiển thị thông tin theo dữ liệu mà người dùng search.

Search.html

File HTML này tương tự ở trên, chỉ có thêm thẻ

// File JavaScript.html

  $[].ready[function[]{
    google.script.run.withSuccessHandler[showDataTable]
      .getAllData[];
  }];
  function showDataTable[dataTable] {
    var header = [];
    dataTable.header.forEach[item => {
       header.push[{title: item}];
    }]
    $['
# table'].DataTable[{
      data: dataTable.data,
      columns: header,
      searching: false,
      info: false
    }]
  }

0 để người dùng nhập nội dung cần tìm.



    

Search your invoice.

Input your phone number to search your invoice. Don't include country code, space and other special character.

Search

JavaScript.html

Khi người dùng nhấn button Search sau khi đã input dữ liệu thì client-side sẽ dùng class google.script.run để thực thi hàm

// File JavaScript.html

  $[].ready[function[]{
    google.script.run.withSuccessHandler[showDataTable]
      .getAllData[];
  }];
  function showDataTable[dataTable] {
    var header = [];
    dataTable.header.forEach[item => {
       header.push[{title: item}];
    }]
    $['
# table'].DataTable[{
      data: dataTable.data,
      columns: header,
      searching: false,
      info: false
    }]
  }

1 ở file code Apps Script. Sau khi return thì thêm dữ liệu vào Data Tables instance đã khởi tạo.


  function handleSearch[] {
    // remove data in the previous search
    if [$.fn.DataTable.isDataTable['
# result']] {
      $['
# result'].DataTable[].clear[].draw[];
    }
    $['
# searchBtn'].attr['disabled', true];
    // get value
    let input = document.getElementById['searchText'].value;
    // validation
    // request server-side
    google.script.run
       .withSuccessHandler[onSuccess]
       .withFailureHandler[onFailure]
      .searchByPhone[input];
    // render response see function onSuccess[]
  };
  function onSuccess[result] {
    if [$.fn.DataTable.isDataTable['
# result']] {
      appendDataTable['
# result', result.data];
    } else {
      renderTable['
# result', result];
    }
    $['
# searchBtn'].removeAttr['disabled'];
  };
  function appendDataTable[elementSelector, rowData] {
    $[elementSelector].DataTable[].rows.add[rowData].draw[];
  }
  function renderTable[elementSelector, option] {
    var table = $[elementSelector];
    var field = [];
    option.header.forEach[name => {
      field.push[{title: name}];
    }];
    table.DataTable[{
      data: option.data,
      columns: field,
      paging: false,
      ordering: true,
      info: false,
      searching: false
      }]; 
  }
  function onFailure[] {
    window.alert['Đã xảy ra lỗi khi truy cập file.']
  }

Route

Web app của chúng ta giờ đã có 2 trang nên viết lại hàm

// File JavaScript.html

  $[].ready[function[]{
    google.script.run.withSuccessHandler[showDataTable]
      .getAllData[];
  }];
  function showDataTable[dataTable] {
    var header = [];
    dataTable.header.forEach[item => {
       header.push[{title: item}];
    }]
    $['
# table'].DataTable[{
      data: dataTable.data,
      columns: header,
      searching: false,
      info: false
    }]
  }

2 để thêm tham số p.

function doGet[e] {
  var page = e.parameter.p || 'Index';
  return HtmlService.createTemplateFromFile[page]
    .evaluate[];
}
function searchByPhone[input] {
  var range = sheet.getDataRange[];
  var data = range.getValues[];
  var header = data[0];
  var phoneCol = header.indexOf['Phone'];
  var result = data.filter[function[row] {
      return row[phoneCol] === input
    }];
  return {
    header: getHeaderArr[],
    data: result
    };
}

Như vậy, chúng ta đã xây dựng được chức năng search cơ bản để hiển thị dữ liệu lên web app Apps Script từ Google Sheets. Để hoàn thiện chức năng search này thì bạn có thể thực hiện validate search text và thêm loader để báo hiệu trạng thái load dữ liệu cho người dùng biết [giống phần 1], cũng như xử lý lỗi trong một số tình huống như không tìm thấy dữ liệu, người dùng chỉnh sửa tham số p nên không tìm thấy file.

Chủ Đề