尝试构建图表时出现空表错误

问题描述 投票:0回答:1

我在 Google Apps 脚本中编写了一个脚本,用于生成 PDF 格式的测试结果报告,并显示在电子表格中。显然脚本是正确的,但显然不是,因为每次它都会返回错误

“异常:无法使用空数据表创建图表。”

有人对该怎么做有建议吗?

脚本如下,我还在电子表格中打印了部分数据。

// Constants that store specific Google Drive files and folder IDs
const DOCID = '1cfVmsXj1rtmWEM3NL28oTiDPsGjxQelv8aHoqkw4brw'; // The ID of the Google Document template
const FOLDERID = '1NqdCopDxoyANKcmfkXJCnh4pE6AvNNN5'; // The ID of the target Google Drive folder

// This function runs every time the Google Sheet is opened
function onOpen() {
    // Get the UI of the Google Sheet and add menu items
    SpreadsheetApp.getUi()
        .createMenu('Test result reports')
        .addItem('Generate reports', 'generateReports')
        .addItem('Send reports', 'sendReports')
        .addToUi();
}

// Helper function to validate email addresses
function isValidEmail(email) {
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return regex.test(email);
}

// FUNCTION THAT GENERATES THE TEST REPORTS
function generateReports() {

    const activeSpreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId(); // Get the active spreadsheet's ID dynamically
    const sheet = SpreadsheetApp.openById(activeSpreadsheetId).getSheetByName('Envio de report');
    const data = sheet.getDataRange().getValues();
    const temp = DriveApp.getFileById(DOCID);
    const folder = DriveApp.getFolderById(FOLDERID);
    const rows = data.slice(1); // Skip the headers row
    const skillNames = ["Objetividade Argumentativa", "Análise sob Incerteza", "Análise de Padrões", "Inteligência Espacial", "Pensamento Matemático", "Total Cognitivo", "Inglês"]; // Skill names array

    rows.forEach((row, index) => {
        const email = row[2];

        // Check if report hasn't been generated yet (column AR in the row must be empty)
        if (row[43] == '') {
            const file = temp.makeCopy(folder);
            const doc = DocumentApp.openById(file.getId());
            const body = doc.getBody();

            // Loop through the spreadsheet header row to replace placeholders in the document body
            data[0].forEach((heading, i) => {
                body.replaceText(`{${heading}}`, row[i]);
            });

            // Replace placeholders in the document header
            const headers = doc.getHeader();
            if (headers) {
                data[0].forEach((heading, i) => {
                    headers.replaceText(`{${heading}}`, row[i]);
                });
            }

            // Generate chart comparing candidate's score, top quintile average, and median score
            const candidateScoresIndices = [4, 7, 10, 13, 16, 19, 22];
            const topQuintileIndices = candidateScoresIndices.map(index => index + 1);
            const medianIndices = candidateScoresIndices.map(index => index + 2);

            // Log the row values to debug
            Logger.log('Row values: ' + row);
            Logger.log('Candidate Scores: ' + candidateScoresIndices.map(i => row[i]));
            Logger.log('Top Quintile: ' + topQuintileIndices.map(i => row[i]));
            Logger.log('Median: ' + medianIndices.map(i => row[i]));

            const dataTable = Charts.newDataTable()
                .addColumn(Charts.ColumnType.STRING, 'Habilidade')
                .addColumn(Charts.ColumnType.NUMBER, 'Nota')
                .addColumn(Charts.ColumnType.NUMBER, 'Top Quintile')
                .addColumn(Charts.ColumnType.NUMBER, 'Mediana')
                .build();

            // Use the provided skill names and format the scores
            for(let i = 0; i < candidateScoresIndices.length; i++) {
                dataTable.addRow([skillNames[i], formatAsPercentage(row[candidateScoresIndices[i]]), formatAsPercentage(row[topQuintileIndices[i]]), formatAsPercentage(row[medianIndices[i]])]);
            }

            const chartBuilder = Charts.newComboChart()
                .setDataTable(dataTable)
                .setDimensions(600, 400)
                .setRange(0, 1)
                .setSeries([{
                    type: Charts.ChartType.BARS,
                    targetAxisIndex: 0,
                    color: '#7B70AD'
                }, {
                    type: Charts.ChartType.LINE,
                    targetAxisIndex: 0,
                    color: '#B46AAB'
                }, {
                    type: Charts.ChartType.STEPPED_AREA,
                    targetAxisIndex: 0,
                    color: '#D8D5E7'
                }])
                .setLegendPosition(Charts.Position.BOTTOM);

            const chart = chartBuilder.build();

            // Insert the chart where bookmark named 'CHART_POSITION' is
            const bookmark = doc.getBookmarkById('CHART_POSITION');
            const position = bookmark.getPosition();
            body.insertImage(position, chart.getAs('image/png')).setAltDescription('Resultado por habilidade').setWidth(600).setHeight(400);

            // Set the name of the new document based on the user name
            doc.setName('Relatório individual - ' + row[1]);

            // Convert doc to PDF
            const blob = doc.getAs(MimeType.PDF);
            doc.saveAndClose();

            // Save the PDF in the specified folder and set its name
            folder.createFile(blob).setName('[enter image description here](https://i.stack.imgur.com/imgl6.png)Relatório individual - ' + row[1] + '.pdf');

            // Set the report creation date in column U for the current row
            const creationDateCell = sheet.getRange(index + 2, 21); // +2 because arrays are 0-indexed and we skipped the header row
            const formattedDate = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'dd/MM/yyyy');
            creationDateCell.setValue(formattedDate);
        }
    });
}

// Helper function to format values as percentages
function formatAsPercentage(value) {
    return (value * 100).toFixed(0) + '%';
}
javascript google-apps-script google-visualization
1个回答
0
投票

这是构建散点图的简单示例。正如我所指出的,

newComboChart
不是
Charts
的方法。我还注意到
ScatterChartBuilder
DataTableBuilder
的大多数方法都会返回
this
,因此您不需要链接方法。

代码.gs

function drawChart() {
  let spread = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = spread.getSheetByName("Scatter");
  let data = sheet.getDataRange().getValues();
  let header = data.shift();

  let dataTable = Charts.newDataTable();

  dataTable.addColumn(Charts.ColumnType.NUMBER,header[0]);
  dataTable.addColumn(Charts.ColumnType.NUMBER,header[1]);
  dataTable.addColumn(Charts.ColumnType.NUMBER,header[2]);

  data.forEach( row => dataTable.addRow(row) );
  dataTable = dataTable.build();

  let chart = Charts.newScatterChart()
                .setDataTable(dataTable)
                .build();

  let doc = DocumentApp.create("TestChart");
  let body = doc.getBody();
  body.appendImage(chart.getBlob());
}

截图

参考

© www.soinside.com 2019 - 2024. All rights reserved.