26

Tôi có hệ thống cơ sở dữ liệu kế thừa (không truy cập được web) trên máy chủ tạo báo cáo CSV hoặc XLS vào thư mục Google Drive. Hiện tại, tôi đang mở các tệp đó trong giao diện web của Drive theo cách thủ công và chuyển đổi chúng thành Google Trang tính.Cách tự động nhập dữ liệu từ tệp CSV hoặc XLS được tải lên vào Google Trang tính

Tôi muốn điều này tự động hơn để tôi có thể tạo công việc thêm/chuyể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 thành .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 không?

+0

google-spreadsheet-api có thể nhập dữ liệu vào bảng tính google hiện có. Tôi nghi ngờ API Drive có cách để nhập dưới dạng tệp bảng tính mới, vì tôi nghĩ rằng tôi đã thấy một số mã để nhập trên SO. – eddyparkinson

+0

Tò mò về cách hệ thống cũ của bạn tạo tệp báo cáo trực tiếp lên Google Drive. Nó có sử dụng API Drive hoặc một số cơ chế khác không? Nếu trước đây, bạn có thể thay đổi mã để tự động chuyển đổi thành Trang tính chứ không phải là tệp CSV sau xử lý. – wescpy

Trả lời

30

Bạn có thể nhập dữ liệu từ tệp csv trong Drive của mình vào Google Trang tính hiện có bằng Google Apps Script, thay thế/thêm dữ liệu nếu 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 của bạn nơi tệp CSV được lưu/tải lên; b) tệp CSV được đặt tên là "report.csv" và dữ liệu trong đó được phân tá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 nhận xét 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 time-driven trigger trong dự án kịch bản của bạn để chạy importData() chức năng một cách thường xuyên (ví dụ mỗi đêm tại 1:00), vì vậy tất cả các bạn phải làm là đặt tập tin report.csv mới vào thư mục Drive định và nó sẽ tự động được xử lý vào lần chạy được lên lịch tiếp theo.

Nếu bạn hoàn toàn PHẢI làm việc với tệp Excel thay vì CSV, thì bạn có thể sử dụng mã này bên dưới. Để ứng dụng hoạt động, bạn phải bật API Drive trong Dịch vụ nâng cao của Google trong tập lệnh của bạn và trong Developers Console (xem How to Enable Advanced Services để 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()); 
} 

The above code is also available as a gist here.

+0

Điều này là hoàn hảo, cảm ơn bạn. Vì một số báo cáo chứa dấu phẩy và, thật đáng buồn, chương trình cũ không thể sử dụng một phân cách khác, có cách nào để nhập theo cách này cho bảng tính Excel không? – youcantexplainthat

+0

Thực ra, tôi có một câu hỏi tiếp theo nếu bạn không phiền. Với mục đích báo cáo doanh nghiệp nhỏ (không có nhiều dữ liệu), đâu là nơi tốt nhất để giữ dữ liệu? Trong một bộ Google Trang tính, hoặc sử dụng cơ sở dữ liệu AppEngine của họ có ý nghĩa không? – youcantexplainthat

+0

Nếu sự cố cũ của bạn xuất ra csv đúng cách, kèm theo bất kỳ giá trị nào bằng dấu phẩy trong đó vào dấu ngoặc kép, thì tốt, tập lệnh sẽ hoạt động. Nếu bạn phải sử dụng tệp Excel, thì [mã ở đây để chuyển đổi tệp Excel sang Bảng tính Google] (https://gist.github.com/soundTricker/4661041) sẽ thực hiện thủ thuật. Trong các thử nghiệm của tôi, nó làm việc với cả hai tệp xls và xlsx. Để sử dụng mã đó, bạn phải bật API Drive trong Dịch vụ nâng cao của Google trong dự án của bạn VÀ trong Developers Console. Khóa nhà phát triển mà mã yêu cầu là khóa Máy chủ mà bạn có thể tạo trong Dev Console. – azawaza

6

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

?convert=true 

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

EDIT: Đây là tài liệu về các thông số có sẵn: https://developers.google.com/drive/v2/reference/files/insert

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

Upload CSV to Google Drive Spreadsheet using Drive v2 API

+1

Chương trình báo cáo không cho phép các cuộc gọi HTTP. Tất cả nó có thể làm là tạo ra CSV hoặc XLS và đặt nó trong một thư mục (mà xảy ra là một thư mục ổ google). – youcantexplainthat

+1

Tôi tự hỏi ... Có thể gọi điều này từ một bản ghi, để nó chỉ chuyển đổi và tập tin tôi đưa vào một thư mục nhất định? – youcantexplainthat

+0

Thông số '? Convert = true' chỉ áp dụng cho tệp được tải lên trong cùng yêu cầu http đó. Kiểm tra cài đặt của ứng dụng Google Drive bạn sử dụng, xem liệu có các cài đặt xử lý chuyển đổi hay không. Phía sau hậu trường, chương trình đó sẽ sử dụng các yêu cầu http để đồng bộ hóa các tệp của bạn. – Matt

4

(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ó dựa trên bản dịch thủ công bằng Apps Script và mã có thể không linh hoạt, yêu cầu bảo trì. Nếu hệ thống cũ của bạn tự động tạo tệp CSV, tốt nhất là họ nên chuyển sang một thư mục khác để xử lý tạm thời (nhập [tải lên Google Drive & chuyển đổi] vào tệp Google Trang tính).

Suy nghĩ của tôi là cho phép API Drive thực hiện tất cả việc nâng hạng nặng.Đội Google Drive APIreleased v3 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 hoạt động của tệp. Cũng không còn cờ chuyển đổi nữa - bạn chỉ cần chỉ định MIMEtypes ... hãy tưởng tượng điều đó!

Tài liệu cũng đã được cải thiện: hiện có special guide devoted to uploads (đơn giản, đa phần và có thể tiếp tục lại) đi kèm với mã mẫu trong Java, Python, PHP, C# /. NET, Ruby, JavaScript/Node.js và iOS/Obj-C nhập các tệp CSV vào định dạng Google Trang tính như mong muốn.

Dưới đây là một giải pháp Python thay thế cho các tệp ngắn ("tải lên đơn giản") nơi bạn không cần lớp apiclient.http.MediaFileUpload. Đoạn mã này giả định mã xác thực của bạn hoạt động ở đ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'])) 

Hơn thế nữa, chứ không phải tải lên My Drive, bạn muốn tải lên một (hoặc nhiều) thư mục cụ thể (s), có nghĩa là bạn muốn thêm thư mục mẹ ID (s) để METADATA. (Cũng xem mẫu mã trên this page.) Cuối cùng, không có tệp .gsheet "gốc" - tệp đó chỉ có 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 làm mã giả để chuyển sang ngôn ngữ hệ thống của bạn. 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à xóa đi thư mục tạm thời của tệp CSV mà hệ thống cũ của bạn đã viết.

Các vấn đề liên quan