26

Ich habe ein Legacy-Datenbanksystem (nicht webfähig) auf einem Server, der CSV- oder XLS-Berichte in einem Google Drive-Ordner generiert. Momentan öffne ich diese Dateien manuell in der Google Drive-Weboberfläche und konvertiere sie in Google Tabellen.So importieren Sie automatisch Daten aus hochgeladenen CSV- oder XLS-Dateien in Google Tabellen

Ich würde lieber dies automatisch sein, damit ich Jobs erstellen kann, die die Daten in anderen Blättern anhängen/umwandeln und grafisch darstellen.

Ist es möglich, eine native .gsheet-Datei auszugeben? Oder gibt es eine Möglichkeit, CSV oder XLS programmgesteuert in .gsheet zu konvertieren, nachdem Sie sie in Google Drive oder über ein Windows-basiertes Skript/Dienstprogramm gespeichert haben?

+0

Google-Tabellenkalkulation-API kann Daten in eine vorhandene Google-Tabelle importieren. Ich vermute, dass die Drive-API eine Möglichkeit zum Importieren als neue Tabellendatei bietet, da ich glaube, dass ich Code für den Import auf SO gesehen habe. – eddyparkinson

+0

Neugierig darauf, wie Ihr Altsystem die Berichtsdateien direkt in Google Drive generiert. Verwendet es die Drive API oder einen anderen Mechanismus? Wenn Sie Ersteres verwenden, können Sie den Code für die automatische Konvertierung in Sheets im Handumdrehen ändern, anstatt CSV-Dateien nachbearbeiten zu müssen. – wescpy

Antwort

30

Sie können Daten aus einer csv-Datei in Google Drive mithilfe von Google Apps Script in ein vorhandenes Google-Blatt importieren und die Daten nach Bedarf ersetzen/anhängen.

Unten finden Sie einen Beispielcode. Es wird davon ausgegangen, dass: a) Sie haben einen bestimmten Ordner in Ihrem Laufwerk, wo die CSV-Datei gespeichert/hochgeladen wird; b) die CSV-Datei heißt "report.csv" und die darin enthaltenen Daten werden durch Kommas getrennt; und c) Die CSV-Daten werden in eine bestimmte Tabelle importiert. Siehe Kommentare im Code für weitere Details.

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); 
}; 

Sie dann time-driven trigger in Ihrem Skript-Projekt erstellen können importData() Funktion in regelmäßigen Abständen (zB jede Nacht um 01.00 Uhr) zu laufen, also alles, was Sie tun müssen, ist setzt neue Datei report.csv in die vorgesehenen Drive-Ordner und wird beim nächsten geplanten Lauf automatisch verarbeitet.

Wenn Sie unbedingt mit Excel-Dateien anstelle von CSV arbeiten müssen, können Sie diesen Code unten verwenden. Damit es funktioniert, müssen Sie die Drive API in den erweiterten Google-Diensten in Ihrem Skript und in der Developers Console aktivieren (Details finden Sie unter).

/** 
* 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

Das ist perfekt, danke. Da einige der Berichte Kommas enthalten und das Legacy-Programm leider keine anderen Trennzeichen verwenden kann, gibt es eine Möglichkeit, auf diese Weise Excel-Tabellen zu importieren? – youcantexplainthat

+0

Eigentlich habe ich noch eine weitere Frage, wenn es Ihnen nichts ausmacht. Für die Zwecke der Berichterstattung von Kleinunternehmen (nicht viele Daten), wo ist der beste Ort, um die Daten zu halten? In einer Gruppe von Google Tabellen oder ist es sinnvoll, ihre AppEngine-Datenbanken zu verwenden? – youcantexplainthat

+0

Wenn Ihr Legacy-Problem csv korrekt ausgibt, indem Sie beliebige Werte mit Kommas in Anführungszeichen einschließen, dann ist es in Ordnung, das Skript funktioniert. Wenn Sie Excel-Dateien verwenden müssen, dann [der Code hier zum Konvertieren der Excel-Datei in Google Spreadsheet] (https://gist.github.com/soundTricker/4661041) wird den Trick tun. In meinen Tests funktionierte es sowohl mit xls als auch mit xlsx Dateien. Um diesen Code zu verwenden, müssen Sie die Drive API in den erweiterten Google-Diensten in Ihrem Projekt und in der Developers Console aktivieren. Der Entwicklerschlüssel, den der Code benötigt, ist der Serverschlüssel, den Sie in der Dev-Konsole erstellen können. – azawaza

6

Sie können Google Drive erhalten automatisch csv-Dateien in Google Tabellen konvertieren von

?convert=true 

bis zum Ende der api-URL anfügt Sie anrufen.

EDIT: Hier ist die Dokumentation über die verfügbaren Parameter: https://developers.google.com/drive/v2/reference/files/insert

Auch während für den obigen Link Suche, fand ich diese Frage wurde hier schon beantwortet:

Upload CSV to Google Drive Spreadsheet using Drive v2 API

+1

Das Berichtsprogramm lässt keine HTTP-Aufrufe zu. Alles, was es tun kann, ist das Erstellen der CSV oder XLS und legen Sie es in einem Ordner (der zufällig ein Google Drive-Ordner ist). – youcantexplainthat

+1

Ich frage mich ... Ist es möglich, dies aus einem appscript, so dass es nur konvertieren und Datei, die ich in einen bestimmten Ordner? – youcantexplainthat

+0

Der Parameter '? Convert = true' gilt nur für die Datei, die in derselben HTTP-Anforderung hochgeladen wurde. Überprüfen Sie die Einstellungen der Google Drive-Anwendung, die Sie verwenden, und prüfen Sie, ob Einstellungen für die Conversion vorhanden sind. Hinter den Kulissen verwendet das Programm HTTP-Anfragen, um Ihre Dateien zu synchronisieren. – Matt

4

(Mär 2017) Die angenommene Antwort ist nicht die beste Lösung. Es basiert auf manueller Übersetzung mit Hilfe von Apps Script und der Code ist unter Umständen nicht belastbar und muss gewartet werden. Wenn Ihr Altsystem CSV-Dateien automatisch generiert, sollten Sie es am besten in einen anderen Ordner für die temporäre Verarbeitung (Importieren [Hochladen auf Google Drive & Konvertieren] in Google Tabellen-Dateien) verschieben.

Mein Gedanke ist es, die Drive-API das ganze Heavy-Lifting durchführen zu lassen.Die Google Drive API Team released v3 am Ende des Jahres 2015, und in dieser Version, insert() änderte die Namen in create(), so dass die Dateioperation besser widerspiegeln. Es gibt auch kein Convert-Flag mehr - Sie geben nur MIMEtypes an ... stellen Sie sich das vor!

Die Dokumentation wurde ebenfalls verbessert: Es gibt jetzt eine special guide devoted to uploads (einfach, mehrteilig und fortsetzbar), die mit Beispielcode in Java, Python, PHP, C#/.NET, Ruby, JavaScript/Node.js und iOS geliefert wird/Obj-C, das CSV-Dateien wie gewünscht in das Google Tabellenformat importiert.

Unten ist eine alternative Python-Lösung für kurze Dateien ("einfacher Upload"), wo Sie nicht benötigen die apiclient.http.MediaFileUpload Klasse. In diesem Code-Schnipsel wird davon ausgegangen, dass der Authentifizierungscode für den Dienstendpunkt DRIVE mit einem minimalen Authentifizierungsbereich von https://www.googleapis.com/auth/drive.file verwendet wird.

# 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'])) 

Noch besser wäre es, anstatt zu My Drive hochladen, würden Sie zu einem (oder mehreren) bestimmten Ordner (n) laden, dh Sie können den übergeordneten Ordner ID hinzufügen würde (n) zu METADATA. (Siehe auch das Codebeispiel unter this page.) Schließlich gibt es keine native .gsheet "Datei" - diese Datei hat nur einen Link zum Online-Blatt, also was Sie wollen, ist was Sie wollen.

Wenn Sie Python nicht verwenden, können Sie das obige Snippet als Pseudocode verwenden, um es in Ihre Systemsprache zu portieren. Unabhängig davon, es gibt viel weniger Code zu pflegen, weil es keine CSV-Parsing gibt. Das einzige, was übrig bleibt, ist, den CSV-Datei-Temp-Ordner wegzublasen, an den Ihr Altsystem geschrieben hat.