从谷歌电子表格到JS数组

时间:2016-07-18 14:25:03

标签: javascript arrays excel google-apps-script

我有一个谷歌电子表格,我公开了所有,并希望从那里转到JS阵列。我一直在玩它并尝试将其转换为JSON然后转换为数组,但我没有运气。有没有办法从我的电子表格转到2d JS数组,然后我可以运行函数。

因此,如果电子表格如下所示:

NAME  COLOR  SIZE
MARK   BLUE     6
DAVE    RED     8

数组将为2d数组,使得值[0] [0]为MARK,[1] [0]为蓝色,[0] [1]为DAVE等。

非常感谢任何帮助

2 个答案:

答案 0 :(得分:2)

编辑:由于我们使用的是Google API4,并且相应地更新了该模块,并且由于API3将于9月停用,因此我相应地更新了代码。

我知道这已经很老了,但是如果其他任何人都在寻找答案:

我玩过用JS操作Google电子表格的过程,并希望从一个包含多个工作表的工作表转到一个我可以轻松用于其他功能的数组。

因此,我编写了一个程序来访问工作表,从内部获取所有工作表(选项卡),减少全为空的行和列,然后返回一个新的工作表数组。 工作表数组中的每个元素都代表Excel工作表中的工作表。 而且,每个元素都有一个二维数组的单元格,例如:

cellsArr:[[row],[col]]

要运行该程序,只需将YOUR_CLIENT_SECRET.json替换为您的客户端机密json文件,然后将ENTER_GOOGLE_SPREADSHEET_ID_FROM_URL替换为该URL中电子表格的ID。例如:

docs.google.com/spreadsheets/d/ 1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms / edit#gid = 0 1

然后运行:

getWorksheet(ENTER_GOOGLE_SPREADSHEET_ID_FROM_URL);

这将返回一个承诺,该承诺将被解决到修订的工作表中(如上所述)。 请注意,reduceRowsCols()从每个工作表中删除空的行和列。它会删除第一列单元格为空的每一行,以及第一行单元格为空的每一列,因此[i][0]==null的每一行和[0][i]==null的每一列都将删除。 只需从代码中删除reduceRowsCols()即可取消

  

  const fs = require('fs');

const {GoogleSpreadsheet} = require('google-spreadsheet'),
    creds = require('./client_secret.json'), 

/**
 * @Description Authenticate with the Google Spreadsheets API using credentials json. 
 * @param {string} spreadsheet_id  - spreadsheet id to get. Get this from the URL of the spreadsheet
 * Returns the entire raw worksheet.
 * */
async function accessSpreadsheet(spreadsheet_id) {
    const doc = new GoogleSpreadsheet(spreadsheet_id);
    await doc.useServiceAccountAuth(creds);
    await doc.loadInfo();
    console.log(`${getCurrentTime()}: Loaded raw doc ${doc.title}`);
    return doc;
}
/**
 * @Description This is an async function to retrieve the raw worksheet
 * @param {string} spreadsheet_id  - spreadsheet id to get. Get this from the URL of the spreadsheet
 * */
async function getWorksheet(spreadsheet_id) {
    try {
        let res = await accessSpreadsheet(spreadsheet_id);
        console.log(`${getCurrentTime()}: Organizing sheets for extraction...`);
        res = await getCondensedWorksheets(res.sheetsByIndex);
        createSheetsCopy(res);
        return res;
    } catch (e) {
        throw (e);
    }
}

/**
 * @param worksheetsArr
 */
async function getCondensedWorksheets(worksheetsArr) {
    if (!Array.isArray(worksheetsArr)) {
        throw `getCondensedWorksheets: worksheets variable passed is not an array. Object passed:\n${worksheetsArr}`;
    }
    let revisedArr = [];
        for (let i = 0; i < worksheetsArr.length; i++) {
        // for (let i = 0; i < 1; i++) {
        
        revisedArr.push(await worksheetsArr[i].getRows().then((res)=>{
            let thisRevised = {
                id: worksheetsArr[i]._rawProperties.sheetId,
                title: worksheetsArr[i].title,
                rowCount: worksheetsArr[i].rowCount,
                colCount: worksheetsArr[i].columnCount,
                getRows: worksheetsArr[i].getRows,
                getHeaders: worksheetsArr[i].headerValues,
                getCells    :   res.map( row => {return(row._rawData);}),
                resize: worksheetsArr[i].resize,
            }                
            return getCells2dArray(thisRevised);
        }))
    }
    return Promise.all(revisedArr).then(()=>{
        return revisedArr;
    })    
}

/**
 * @param {array} thisSheet - a single sheet (tab)
 */
function getCells2dArray(thisSheet) {
        let sheetCellsArr = [];
       
        sheetCellsArr.push(thisSheet.getHeaders);
        thisSheet.getCells.map(row => {
            sheetCellsArr.push(row);
        })
        thisSheet.cellsArr = sheetCellsArr;   
        delete thisSheet.getCells;
        reduceRowsCols(thisSheet); 
    return thisSheet;
}

function reduceRowsCols(thisSheet) {
    for (let i = 0; i < thisSheet.cellsArr.length; i++) {
        if (thisSheet.cellsArr[i][0] == null) {
            thisSheet.cellsArr.slice(0, i);
            break;
        }
    }

    for (let i = 0; i < thisSheet.cellsArr[0].length; i++) {
        if (thisSheet.cellsArr[0][i] == null) {
            thisSheet.cellsArr[0].slice(0, i);
            break;
        }
    }
}

const getCurrentTime = function (){
    var date = new Date();
    return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}:${date.getMilliseconds()}`
}

module.exports = {getWorksheet};

答案 1 :(得分:0)

GAS中有两种方法允许读取单元格中的值。它们是.getValue().getValues()。如上所述,.getValue()仅检索范围中左上角单元格的值。 .getValues()检索您范围内所有值的2D数组。

下面的代码定义了读取后续范围所需的变量。范围定义(基于您的示例)从第二行开始(忽略您的标题行),继续3列,然后到内容的最后一行。

您会注意到我们找到了.getLastRow(),但后来定义了要读取的行数lastRow - 1。这是因为.getLastRow()为我们提供了包含数据的最后一行的位置;或者更简单地说,是一个有多少行有数据的整数。如果我们有20行数据,那么包括我们想要忽略的标题行。在将我们的范围向下移动一行后读取20行将包括第一个空行。读取最后一个数据填充行后,读取19行代替。

请注意,.getRange()需要输入.getRange(startRow, startColumn, numRows, numColumns)。可以在GAS参考表here

中找到更多详细信息和说明
function myFunction() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSpreadsheet();
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange(2, 1, (lastRow - 1), 3);
  var dataArray = range.getValues();
}

然后可以像调用Javascript一样调用,定义,读取等数组中的值。您会在GAS参考中发现许多方法都有单数和复数版本,例如.getBackground().getBackgrounds()。这些将采用与.getValue().getValues()相同的比较方式。

注意即使您的范围是单行但有很多列也可能会有所帮助,.getValues()会为您提供一个二维数组,其中所有值都以[0]开头,作为唯一可能的值row是0。