it-swarm-vi.tech

Cách tự động nhập dữ liệu từ tệp CSV hoặc XLS đã tải lên vào Google Sheets

Tôi có một hệ thống cơ sở dữ liệu cũ (không thể truy cập web) trên máy chủ tạo báo cáo CSV hoặc XLS cho thư mục Google Drive. Hiện tại, tôi đang tự mở các tệp đó trong giao diện web Drive và chuyển đổi chúng sang Google Sheets.

Tôi thà điều này là tự động để tôi có thể tạo các công việc nối/biến đổi và vẽ biểu đồ dữ liệu trong các trang tính khác.

Có thể xuất tệp .gsheet gốc không? Hoặc có cách nào để chuyển đổi CSV hoặc XLS sang .gsheet theo chương trình sau khi lưu nó vào Google Drive trong Google Apps hoặc thông qua tập lệnh/tiện ích dựa trên Windows?

32
youcantexplainthat

Bạn có thể nhập dữ liệu theo chương trình từ tệp csv trong Drive vào Google Sheet hiện có bằng Google Apps Script, thay thế/nối thêm dữ liệu khi cần.

Dưới đây là một số mã mẫu. Nó giả định rằng: a) bạn có một thư mục được chỉ định trong Drive nơi tệp CSV được lưu/tải lên; b) tệp CSV được đặt tên là "báo cáo.csv" và dữ liệu trong đó được phân cách bằng dấu phẩy; và c) dữ liệu CSV được nhập vào bảng tính được chỉ định. Xem ý kiến ​​trong mã để biết thêm chi tiết.

function importData() {
  var fSource = DriveApp.getFolderById(reports_folder_id); // reports_folder_id = id of folder where csv reports are saved
  var fi = fSource.getFilesByName('report.csv'); // latest report file
  var ss = SpreadsheetApp.openById(data_sheet_id); // data_sheet_id = id of spreadsheet that holds the data to be updated with new report data

  if ( fi.hasNext() ) { // proceed if "report.csv" file exists in the reports folder
    var file = fi.next();
    var csv = file.getBlob().getDataAsString();
    var csvData = CSVToArray(csv); // see below for CSVToArray function
    var newsheet = ss.insertSheet('NEWDATA'); // create a 'NEWDATA' sheet to store imported data
    // loop through csv data array and insert (append) as rows into 'NEWDATA' sheet
    for ( var i=0, lenCsv=csvData.length; i<lenCsv; i++ ) {
      newsheet.getRange(i+1, 1, 1, csvData[i].length).setValues(new Array(csvData[i]));
    }
    /*
    ** report data is now in 'NEWDATA' sheet in the spreadsheet - process it as needed,
    ** then delete 'NEWDATA' sheet using ss.deleteSheet(newsheet)
    */
    // rename the report.csv file so it is not processed on next scheduled run
    file.setName("report-"+(new Date().toString())+".csv");
  }
};


// http://www.bennadel.com/blog/1504-Ask-Ben-Parsing-CSV-Strings-With-Javascript-Exec-Regular-Expression-Command.htm
// This will parse a delimited string into an array of
// arrays. The default delimiter is the comma, but this
// can be overriden in the second argument.

function CSVToArray( strData, strDelimiter ) {
  // Check to see if the delimiter is defined. If not,
  // then default to COMMA.
  strDelimiter = (strDelimiter || ",");

  // Create a regular expression to parse the CSV values.
  var objPattern = new RegExp(
    (
      // Delimiters.
      "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +

      // Quoted fields.
      "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +

      // Standard fields.
      "([^\"\\" + strDelimiter + "\\r\\n]*))"
    ),
    "gi"
  );

  // Create an array to hold our data. Give the array
  // a default empty first row.
  var arrData = [[]];

  // Create an array to hold our individual pattern
  // matching groups.
  var arrMatches = null;

  // Keep looping over the regular expression matches
  // until we can no longer find a match.
  while (arrMatches = objPattern.exec( strData )){

    // Get the delimiter that was found.
    var strMatchedDelimiter = arrMatches[ 1 ];

    // Check to see if the given delimiter has a length
    // (is not the start of string) and if it matches
    // field delimiter. If id does not, then we know
    // that this delimiter is a row delimiter.
    if (
      strMatchedDelimiter.length &&
      (strMatchedDelimiter != strDelimiter)
    ){

      // Since we have reached a new row of data,
      // add an empty row to our data array.
      arrData.Push( [] );

    }

    // Now that we have our delimiter out of the way,
    // let's check to see which kind of value we
    // captured (quoted or unquoted).
    if (arrMatches[ 2 ]){

      // We found a quoted value. When we capture
      // this value, unescape any double quotes.
      var strMatchedValue = arrMatches[ 2 ].replace(
        new RegExp( "\"\"", "g" ),
        "\""
      );

    } else {

      // We found a non-quoted value.
      var strMatchedValue = arrMatches[ 3 ];

    }

    // Now that we have our value string, let's add
    // it to the data array.
    arrData[ arrData.length - 1 ].Push( strMatchedValue );
  }

  // Return the parsed data.
  return( arrData );
};

Sau đó, bạn có thể tạo kích hoạt theo thời gian trong dự án tập lệnh của bạn để chạy hàm importData() một cách thường xuyên (ví dụ: mỗi tối lúc 1 giờ sáng), vì vậy tất cả những gì bạn phải làm là đưa báo cáo mới. tập tin csv vào thư mục Drive được chỉ định và nó sẽ được xử lý tự động trong lần chạy theo lịch trình tiếp theo.

Nếu bạn hoàn toàn PHẢI làm việc với các tệp Excel thay vì CSV, thì bạn có thể sử dụng mã này bên dưới. Để nó hoạt động, bạn phải kích hoạt API Drive trong Dịch vụ Google nâng cao trong tập lệnh của bạn và trong Bảng điều khiển dành cho nhà phát triển (xem Cách bật dịch vụ nâng cao để biết chi tiết).

/**
 * Convert Excel file to Sheets
 * @param {Blob} excelFile The Excel file blob data; Required
 * @param {String} filename File name on uploading drive; Required
 * @param {Array} arrParents Array of folder ids to put converted file in; Optional, will default to Drive root folder
 * @return {Spreadsheet} Converted Google Spreadsheet instance
 **/
function convertExcel2Sheets(excelFile, filename, arrParents) {

  var parents  = arrParents || []; // check if optional arrParents argument was provided, default to empty array if not
  if ( !parents.isArray ) parents = []; // make sure parents is an array, reset to empty array if not

  // Parameters for Drive API Simple Upload request (see https://developers.google.com/drive/web/manage-uploads#simple)
  var uploadParams = {
    method:'post',
    contentType: 'application/vnd.ms-Excel', // works for both .xls and .xlsx files
    contentLength: excelFile.getBytes().length,
    headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()},
    payload: excelFile.getBytes()
  };

  // Upload file to Drive root folder and convert to Sheets
  var uploadResponse = UrlFetchApp.fetch('https://www.googleapis.com/upload/drive/v2/files/?uploadType=media&convert=true', uploadParams);

  // Parse upload&convert response data (need this to be able to get id of converted sheet)
  var fileDataResponse = JSON.parse(uploadResponse.getContentText());

  // Create payload (body) data for updating converted file's name and parent folder(s)
  var payloadData = {
    title: filename, 
    parents: []
  };
  if ( parents.length ) { // Add provided parent folder(s) id(s) to payloadData, if any
    for ( var i=0; i<parents.length; i++ ) {
      try {
        var folder = DriveApp.getFolderById(parents[i]); // check that this folder id exists in drive and user can write to it
        payloadData.parents.Push({id: parents[i]});
      }
      catch(e){} // fail silently if no such folder id exists in Drive
    }
  }
  // Parameters for Drive API File Update request (see https://developers.google.com/drive/v2/reference/files/update)
  var updateParams = {
    method:'put',
    headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()},
    contentType: 'application/json',
    payload: JSON.stringify(payloadData)
  };

  // Update metadata (filename and parent folder(s)) of converted sheet
  UrlFetchApp.fetch('https://www.googleapis.com/drive/v2/files/'+fileDataResponse.id, updateParams);

  return SpreadsheetApp.openById(fileDataResponse.id);
}

/**
 * Sample use of convertExcel2Sheets() for testing
 **/
 function testConvertExcel2Sheets() {
  var xlsId = "0B9**************OFE"; // ID of Excel file to convert
  var xlsFile = DriveApp.getFileById(xlsId); // File instance of Excel file
  var xlsBlob = xlsFile.getBlob(); // Blob source of Excel file for conversion
  var xlsFilename = xlsFile.getName(); // File name to give to converted file; defaults to same as source file
  var destFolders = []; // array of IDs of Drive folders to put converted file in; empty array = root folder
  var ss = convertExcel2Sheets(xlsBlob, xlsFilename, destFolders);
  Logger.log(ss.getId());
}

Đoạn mã trên cũng có sẵn dưới dạng Gist tại đây .

35
azawaza

Bạn có thể nhận Google Drive để tự động chuyển đổi tệp csv sang Google Sheets bằng cách nối thêm

?convert=true

đến cuối url api bạn đang gọi.

EDIT: Đây là tài liệu về các tham số khả dụng: https://developers.google.com/drive/v2/reference/files/insert

Ngoài ra, trong khi tìm kiếm liên kết trên, tôi thấy câu hỏi này đã được trả lời ở đây:

Tải CSV lên Bảng tính Google Drive bằng API Drive v2

7
Matt

(Mar 2017) Câu trả lời được chấp nhận không phải là giải pháp tốt nhất. Nó phụ thuộc vào bản dịch thủ công bằng Apps Script và mã có thể không được phục hồi, yêu cầu bảo trì. Nếu hệ thống cũ của bạn tự động tạo các tệp CSV, tốt nhất là chúng vào một thư mục khác để xử lý tạm thời (nhập [tải lên Google Drive & chuyển đổi] sang các tệp Google Sheets).

Tôi nghĩ là để API Drive thực hiện mọi công việc nặng nhọc. API Google Drive nhóm phát hành v vào cuối năm 2015 và trong bản phát hành đó, insert() đã đổi tên thành create() để phản ánh tốt hơn các hoạt động tập tin. Cũng không có cờ chuyển đổi nữa - bạn chỉ cần xác định MIMEtypes ... hãy tưởng tượng điều đó!

Tài liệu này cũng đã được cải thiện: giờ đây đã có hướng dẫn đặc biệt dành cho tải lên (đơn giản, nhiều phần và có thể tiếp tục) đi kèm với mã mẫu trong Java, Python, PHP, C # /. NET, Ruby, JavaScript /Node.js và iOS/Obj-C nhập tệp CSV vào định dạng Google Sheets như mong muốn.

Dưới đây là một giải pháp thay thế Python cho các tệp ngắn ("tải lên đơn giản") trong đó bạn không cần apiclient.http.MediaFileUpload lớp học. Đoạn mã này giả định mã xác thực của bạn hoạt động trong đó điểm cuối dịch vụ của bạn là DRIVE với phạm vi xác thực tối thiểu là https://www.googleapis.com/auth/drive.file.

# filenames & MIMEtypes
DST_FILENAME = 'inventory'
SRC_FILENAME = DST_FILENAME + '.csv'
SHT_MIMETYPE = 'application/vnd.google-apps.spreadsheet'
CSV_MIMETYPE = 'text/csv'

# Import CSV file to Google Drive as a Google Sheets file
METADATA = {'name': DST_FILENAME, 'mimeType': SHT_MIMETYPE}
rsp = DRIVE.files().create(body=METADATA, media_body=SRC_FILENAME).execute()
if rsp:
    print('Imported %r to %r (as %s)' % (SRC_FILENAME, DST_FILENAME, rsp['mimeType']))

Tốt hơn hết, thay vì tải lên My Drive, bạn sẽ tải lên một (hoặc nhiều) thư mục cụ thể, nghĩa là bạn sẽ thêm (các) ID thư mục mẹ vào METADATA. (Cũng xem mẫu mã trên trang này .) Cuối cùng, không có tệp ".gsheet" gốc - tệp đó chỉ có một liên kết đến Trang tính trực tuyến, vì vậy những gì ở trên là những gì bạn muốn làm .

Nếu không sử dụng Python, bạn có thể sử dụng đoạn mã ở trên dưới dạng mã giả để chuyển sang ngôn ngữ hệ thống của mình. Bất kể, có ít mã hơn để duy trì vì không có phân tích cú pháp CSV. Điều duy nhất còn lại là thổi bay thư mục tạm thời của tệp CSV mà hệ thống cũ của bạn đã ghi vào.

6
wescpy

Trong trường hợp bất cứ ai cũng sẽ tìm kiếm - Tôi đã tạo tiện ích để tự động nhập các tệp xlsx vào bảng tính google: xls2sheet . Người ta có thể tự động làm điều đó thông qua việc thiết lập cronjob cho ./cmd/sheets-refresh, readme mô tả tất cả. Hy vọng rằng sẽ được sử dụng.

0
Pukeko