简体   繁体   中英

JSON File on Drive to Google sheets

I have a few JSON files on my Google Drive from which I need to extract data into a spreadsheet. I have tried the ImportJson function from github but that is to fetch the JSON file directly from the API but the JSON files I have on my drive are not accessible to me directly from the API.

Can anyone help me in how can I get the JSON stored on the drive to be imported in the Google sheets.

The sample JSON is attached herewith:

 { "gstin": "12ABCDE", "fp": "082019", "b2b": [{ "ctin": "2312ABCDEY", "cfs": "Y", "cfs3b": "Y", "inv": [{ "val": 1072, "itms": [{ "num": 1, "itm_det": { "csamt": 0, "samt": 81.76, "rt": 18, "txval": 908.48, "camt": 81.76 } }], "inv_typ": "R", "pos": "23", "idt": "02-08-2019", "rchrg": "N", "inum": "642", "chksum": "7a58ec7342001040acf4509176ba22ceb03d9ad0ecf7e74d572af0ec4d8429fa" }, { "val": 1072, "itms": [{ "num": 1, "itm_det": { "csamt": 0, "samt": 81.76, "rt": 18, "txval": 908.48, "camt": 81.76 } }], "inv_typ": "R", "pos": "23", "idt": "17-08-2019", "rchrg": "N", "inum": "722", "chksum": "0597afa614e27aa78dc252f2530172007e574f52d1ceea9e433e04f474414bbf" }], "fldtr1": "10-Sep-19", "flprdr1": "Aug-19" }, { "ctin": "22AAB1Z5", "cfs": "Y", "cfs3b": "Y", "inv": [{ "val": 459463, "itms": [{ "num": 1801, "itm_det": { "csamt": 0, "rt": 18, "txval": 389375, "iamt": 70087.5 } }], "inv_typ": "R", "pos": "23", "idt": "30-08-2019", "rchrg": "N", "inum": "2495", "chksum": "15ef392cfd4fd3af2fce1ad8549f93bac20cf17308df9bf9256ae838db45a440" }], "fldtr1": "11-Sep-19", "flprdr1": "Aug-19" }, { "ctin": "23AFEZI", "cfs": "Y", "cfs3b": "Y", "inv": [{ "val": 9350, "itms": [{ "num": 1, "itm_det": { "csamt": 0, "samt": 713.16, "rt": 18, "txval": 7924, "camt": 713.16 } }], "inv_typ": "R", "pos": "23", "idt": "02-08-2019", "rchrg": "N", "inum": "00075", "chksum": "cb4fe40cb2f39f8782a160ece273991daae68b739dfba454ffeb364150d03580" }, { "val": 12312, "itms": [{ "num": 1, "itm_det": { "csamt": 0, "samt": 939.07, "rt": 18, "txval": 10434.09, "camt": 939.07 } }], "inv_typ": "R", "pos": "23", "idt": "10-08-2019", "rchrg": "N", "inum": "00084", "chksum": "1d0fa36c2a7f1ffe7d7c07a829056e4e28fd0300fd593f91ba8216ace4e54f2a" }], "fldtr1": "05-Sep-19", "flprdr1": "Aug-19" }, { "ctin": "23ECVPSQ", "cfs": "Y", "cfs3b": "Y", "inv": [{ "val": 10200, "itms": [{ "num": 1, "itm_det": { "csamt": 0, "samt": 777.97, "rt": 18, "txval": 8644.1, "camt": 777.97 } }], "inv_typ": "R", "pos": "23", "idt": "13-08-2019", "rchrg": "N", "inum": "650", "chksum": "43bcf7c73bf94013344111d95c6f80dea47980ef4bfd3093a33e2c385baa2fdd" }, { "val": 4745, "itms": [{ "num": 1, "itm_det": { "csamt": 0, "samt": 361.91, "rt": 18, "txval": 4021.18, "camt": 361.91 } }], "inv_typ": "R", "pos": "23", "idt": "30-08-2019", "rchrg": "N", "inum": "727", "chksum": "fae1037d879dc718f322e8622a5323344a6cf88b68f68620aaa7ed5d92a15a23" }] }

Data sample to look like this

在此处输入图片说明

You basically want to retrieve all the nested properties in your object (after you've converted the JSON string using JSON.parse() , and write the corresponding key-value pairs to the first two rows of your spreadsheet (key in row 1, value in row 2). When the value is an object, the key will be written in row 1, but row 2 will remain blank (eg b2b ).

In this case, you could use recursion to iterate through and retrieve all the nested properties and values from the object. The function could be something like this:

function allProps(element, array, parent = "") {
  if (typeof element === 'object' && element !== null) {
    if (parent != "") array.push([parent, ""]);
    const entries = Object.entries(element);    
    entries.forEach(entry => {
      const nextParent = Array.isArray(element) ? "" : entry[0];              
      allProps(entry[1], array, nextParent);
    });
  } else {
    array.push([parent, element]);
  }
}

The idea is that, for each value, it checks if the value is an object or a primitive data type. If it's the former, allProps gets called recursively, and if it's the latter, the key-value pair is added to the spreadsheet.

And you could call it this way:

function JSON_to_Spreadsheet() {
  const id = "JSON_FILE_ID"; // Change to your FILE_ID
  const json = DriveApp.getFileById(id).getBlob().getDataAsString(); // Get JSON text from Drive file
  const obj = JSON.parse(json); // JSON text to JS object 
  let array = []; // 2D array where the output will be stored
  allProps(obj, array, parent = ""); // Call function recursively
  array = array[0].map((_, colIndex) => array.map(row => row[colIndex])); // Transpose 2D array
  const sheet = SpreadsheetApp.getActive().getActiveSheet(); // Retrieve active sheet. Change if you want to access another sheet or another spreadsheet
  sheet.getRange(1,1,array.length, array[0].length).setValues(array); // Write 2D array to your sheet.
}

The output looks like this:

在此处输入图片说明

Edit:

If you want each ctin header (apart from the first one, in column D) to occupy a new row, you can do the following once you have retrieved the 2D array:

  • Retrieve an array with all the indexes from array[0] where the header is ctin (excluding the first one).
  • Using these indexes, add each ctin segment to the main array.
  • Write the array to the sheet, taking into account that the different rows have different lengths. If you wanted to use a single setValues (that would be recommended for efficiency purposes), you'd first have to find the maximum length of the inner array elements, and make all the inner arrays have this length.

The function JSON_to_Spreadsheet could be something like this:

function JSON_to_Spreadsheet() {
  const id = "JSON_FILE_ID"; // Change to your FILE_ID
  const json = DriveApp.getFileById(id).getBlob().getDataAsString(); // Get JSON text from Drive file
  const obj = JSON.parse(json); // JSON text to JS object 
  let array = []; // 2D array where the output will be stored
  allProps(obj, array, parent = ""); // Call function recursively
  array = array[0].map((_, colIndex) => array.map(row => row[colIndex])); // Transpose 2D array
  const ctinFirstIndex = 3; // Column D (first ctin)
  const ctinIndexes = array[0].reduce((acc, current, i) => {
    if (current === "ctin" && i !== ctinFirstIndex) {
      acc.push(i);
    } 
    return acc;
  }, []); // Find indexes for all ctin headers
  for (let i = 0; i < ctinIndexes.length; i++) {
    [0,1].forEach(rowIndex => {
      const sliced = array[rowIndex].slice(ctinIndexes[i], ctinIndexes[i + 1]); // Extract ctin segment
      sliced.unshift("","",""); // Columns A to C should be empty
      array.push(sliced); // Add each ctin segment to the 2D array
    });    
  }
  [0,1].forEach(rowIndex => array[rowIndex].splice(ctinIndexes[0])); // Remove other ctin data from first two rows
  const sheet = SpreadsheetApp.getActive().getSheetByName("Copy of Data");
  for (let i = 0; i < array.length; i = i + 2) {
    sheet.getRange(sheet.getLastRow() + 1, 1, 2, array[i].length).setValues(array.slice(i, i + 2));
  } // Write array to sheet. Rows have different dimensions, so cannot be written all at once
}

In this case, the output is:

在此处输入图片说明

This should work for a specific json file. Since opening a JSON file in drive is a bit hard to get the file ID you can use the first function to get the ID.

EDIT:

When you run the first function you can look-up the jsonfile ID in the logs -> View -> Log. Then insert this ID in the second function under // Change file id

//With this function you can get the ID of you json file. After running see the view -> Logs for the info.
function getDriveFileID() {

  //Change id of the drive folder found in the url
  const folderID = "1UN3xxxpE8mXjHHJJF";
  const driveFolder = DriveApp.getFolderById(folderID);
  const driveFiles = driveFolder.getFiles();

  while(driveFiles.hasNext()){
    let file = driveFiles.next();
    console.log(file.getName()," = ",file.getId());
  };
}

function JSON_from_DRIVE() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  //change output sheetname
  const sheet = ss.getSheetByName("Data");
  //Change file id
  const file = DriveApp.getFileById("1IPyU2nxxxxx_lr0F").getBlob().getDataAsString();
  const dataAll = JSON.parse(file);
  const dataRows = dataAll['b2b'];
  
  const rowHeaders = Object.keys(dataRows[0]);
  const rows = [rowHeaders];
  for (var i = 0; i < dataRows.length; i++) {
    var rowData = [];
    for (var j = 0; j < rowHeaders.length; j++) {
      rowData.push(dataRows[i][rowHeaders[j]]); 
    }
    rows.push(rowData);
  }

  sheet.getRange(1,1,rows.length,rows[0].length).setValues(rows); 

}

EDIT: this should work custom for your json file.

//With this function you can get the ID of you json file. After running see the view -> Logs for the info.
function getDriveFileID() {

    //Change id of the drive folder found in the url
    const folderID = "1UN3xxxpE8mXjHHJJF";
    const driveFolder = DriveApp.getFolderById(folderID);
    const driveFiles = driveFolder.getFiles();

    while (driveFiles.hasNext()) {
        let file = driveFiles.next();
        console.log(file.getName(), " = ", file.getId());
    };
}

function JSON_from_DRIVE() {
    const ss = SpreadsheetApp.getActiveSpreadsheet();
    //change output sheetname
    const sheet = ss.getSheetByName("Data");
    //Change file id
    const file = DriveApp.getFileById("1IPyU2nxxxxx_lr0F").getBlob().getDataAsString();
    const dataAll = JSON.parse(file);
    const b2b = dataAll['b2b'];
    const dataRows = [];

    b2b.forEach(base => {
        base.inv.forEach(inv => {
            const obj = {
                "ctin": base.ctin,
                "cfs": base.cfs,
                "cfs3b": base.cfs3b,
                "val": inv.val,
                "num": inv.itms[0].itm_det.csamt,
                "csamt": inv.itms[0].itm_det.csamt,
                "samt": inv.itms[0].itm_det.samt,
                "rt": inv.itms[0].itm_det.rt,
                "txval": inv.itms[0].itm_det.txval,
                "camt": inv.itms[0].itm_det.camt,
                "inv_type": inv.inv_typ,
                "pos": inv.pos,
                "idt": inv.idt,
                "rchrg": inv.rchrg,
                "inum": inv.inum,
                "chksum": inv.chksum,
                "fldtr1": base.fldtr1,
                "flprdr1": base.flprdr1
            }
            newObj.push(obj);
        });
    });

    const rowHeaders = Object.keys(dataRows[0]);
    const rows = [rowHeaders];
    for (var i = 0; i < dataRows.length; i++) {
        var rowData = [];
        for (var j = 0; j < rowHeaders.length; j++) {
            rowData.push(dataRows[i][rowHeaders[j]]);
        }
        rows.push(rowData);
    }

    sheet.getRange(1, 1, rows.length, rows[0].length).setValues(rows);

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM