Comment importer automatiquement des données du fichier CSV ou XLS téléchargé dans Google Sheets

j'ai un ancien système de base de données (non accessible sur le web) sur un serveur qui génère des rapports CSV ou XLS à un dossier de Google Drive. Actuellement, je suis en train d'ouvrir manuellement ces fichiers dans L'interface Web Drive et de les convertir en Google Sheets.

je préférerais que ce soit automatique afin que je puisse créer des emplois qui ajoutent/transforment et graphe les données dans d'autres feuilles.

est-il possible de produire un natif .fichier gsheet? Ou est-il un moyen de convertir les CSV ou XLS to .gsheet par programme après l'enregistrer sur Google Drive, soit dans Google Apps ou via Windows script/utilitaire?

31
demandé sur youcantexplainthat 2014-11-11 01:55:02

3 réponses

vous pouvez programmatiquement importer des données d'un fichier csv dans votre lecteur dans une feuille Google existante en utilisant Google Apps Script, en remplaçant/ajoutant des données si nécessaire.

ci-dessous, il y a un exemple de code. Il suppose que: a) vous avez un dossier désigné dans votre lecteur où le fichier CSV est sauvegardé/téléchargé; b) le fichier CSV est nommé" rapport.csv "et les données dans it délimitées par des virgules; et c) CSV importation des données dans un tableur. Voir les commentaires dans le code pour plus de détails.

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

vous pouvez alors créer time-driven trigger dans votre projet de script pour exécuter importData() fonction sur une base régulière (par exemple chaque nuit à 1AM), de sorte que tout ce que vous avez à faire est de mettre Nouveau rapport.fichier csv dans le dossier du Disque, et il sera automatiquement traité sur la prochaine exécution planifiée.

si vous devez absolument travailler avec les fichiers Excel au lieu de CSV, alors vous pouvez utiliser ce code ci-dessous. Pour que cela fonctionne, vous devez activer L'API de lecteur dans les services Google avancés dans votre script et dans la Console des développeurs (voir comment activer les services avancés pour plus de détails).

/**
 * 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());
}

le code ci-dessus est aussi disponible comme gist ici .

33
répondu azawaza 2014-11-12 03:18:02

vous pouvez obtenir Google Drive pour convertir automatiquement les fichiers csv à Google Sheets en ajoutant

?convert=true

à la fin de l'url api que vous appelez.

EDIT: Voici la documentation sur les paramètres disponibles: https://developers.google.com/drive/v2/reference/files/insert

aussi, en cherchant le lien ci-dessus, j'ai trouvé que cette question a déjà été répondu ici:

Télécharger CSV de Google Drive feuille de calcul à l'aide de Lecteur v2 API

7
répondu Matt 2017-05-23 10:31:02

(Mar 2017) la réponse acceptée n'est pas la meilleure solution. Il s'appuie sur la traduction manuelle à L'aide du Script Apps, et le code peut ne pas être résilient, nécessitant une maintenance. Si votre ancien système autogénère les fichiers CSV, il est préférable qu'ils aillent dans un autre dossier pour le traitement temporaire (importation [uploading to Google Drive & converting] aux fichiers Google Sheets).

mon idée est de laisser L'API D'entraînement faire tout le travail. Le Google Drive API team sorti v3 à la fin de 2015, et dans cette version, insert() changé de nom à create() afin de mieux refléter le fonctionnement du fichier. Il n'y a plus non plus de drapeau convert -- vous spécifiez juste des MIMEtypes... imaginez que!

la documentation a également été améliorée: il y a maintenant un guide spécial consacré au téléchargement (simple, multi-partit, et réutilisable) qui vient avec exemple de code en Java, Python, PHP, C#/.NET, Ruby, JavaScript/Node.js, et iOS / Obj-C qui importe des fichiers CSV dans le format de Google Sheets comme désiré.

ci-dessous est une solution Python alternative pour les fichiers courts ("simple upload") où vous don't besoin de la classe apiclient.http.MediaFileUpload . Cet extrait suppose que votre code d'auth fonctionne lorsque votre endpoint de service est DRIVE avec un champ d'auth minimum de 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']))

mieux cependant, plutôt que de télécharger vers My Drive , vous chargeriez vers un (ou plusieurs) dossier(s) spécifique(s), ce qui signifie que vous ajouteriez le (S) Numéro (s) d'IDENTIFICATION DU (des) dossier (s) parent à METADATA . (Voir aussi l'exemple de code sur cette page . Enfin, il n'y a pas natif .gsheet "fichier" -- Ce fichier a juste un lien vers la feuille en ligne, donc ce qui est ci-dessus est ce que vous voulez faire.

si vous n'utilisez pas Python, vous pouvez utiliser l'extrait ci-dessus comme pseudocode pour le portage vers votre langage système. Indépendamment, il y a beaucoup moins de code à maintenir parce qu'il n'y a pas de parsing CSV. La seule chose qui reste est de souffler le dossier temporaire de fichier CSV le système a écrit à.

6
répondu wescpy 2017-09-19 15:49:59