Google apps script 将表单响应导出为csv谷歌应用程序脚本

Google apps script 将表单响应导出为csv谷歌应用程序脚本,google-apps-script,google-apps,google-forms,Google Apps Script,Google Apps,Google Forms,有没有一种快速的方法可以通过编程将所有响应从Google表单导出到csv?类似于通过脚本调用的“将响应导出到csv” 现在我正在用一种摇滚艺术的方式: 迭代我要导出的表单(~75) 打开每个表单var form=FormApp.openById(formId) 获取响应:var formresponses=form.getResponses()(每种表格的回答从0到700) 迭代响应并获取项响应:var preguntes=formReponses[r].getItemResponses()

有没有一种快速的方法可以通过编程将所有响应从Google表单导出到csv?类似于通过脚本调用的“将响应导出到csv”

现在我正在用一种摇滚艺术的方式:

  • 迭代我要导出的表单(~75)
    • 打开每个表单
      var form=FormApp.openById(formId)
    • 获取响应:
      var formresponses=form.getResponses()(每种表格的回答从0到700)
    • 迭代响应并获取项响应:
      var preguntes=formReponses[r].getItemResponses()
      
      • 对于每个itemResponse,将其转换为csv/json
    • 将响应导出到驱动器文件
这是非常慢,而且一次又一次地挂起,因此我必须导出50个响应,并将它们保存在驱动器分隔的文件中。在下一次执行时(让服务器冷却一段时间后),我将再次执行脚本,跳过在块文件上找到的响应数

此外,我不确定Google在执行
form.getResponses()时是否保持响应顺序(事实上,我发现如果表单被修改,顺序就不一样了)


有更好的方法吗?

在@JackBrown的帮助下,我成功地编写了一个Chrome扩展来下载响应(可能很快在github中)。这将等待
formIds
对象中的每次下载完成,然后提示下一次下载:

'use strict';

function startDownload() {
    const formIds = {
        'Downloads-subfolder-here': {
            'Download-filename-here': '1-cx-aSAMrTK0IHsQkE... {form-id here}',
            'Another-filename-here': '...-dnqdpnEso {form-id here}',
            // ...
        },
        'Another-subfolder-here': {
            'Download-filename-here': '1-cx-aSAMrTK0IHsQkE... {form-id here}',
            'Another-filename-here': '...-dnqdpnEso {form-id here}',
            // ...
        },
    };

    const destFolders = Object.keys(formIds);
    const downloads = [];

    for (let t = 0, tl = destFolders.length; t < tl; t += 1) {
        const destFolder = destFolders[t];
        const forms = Object.keys(formIds[destFolder]);

        for (let f = 0, fl = forms.length; f < fl; f += 1) {
            const formName = forms[f];
            downloads.push({
                destFolder,
                formName,
                url: `https://docs.google.com/forms/d/${formIds[destFolder][formName]}/downloadresponses?tz_offset=-18000000`,
                filename: `myfolder/${destFolder}/${formName.replace(/\//g, '_')}.csv`,
            });
        }
    }

    const event = new Event('finishedDownload');
    const eventInterrupt = new Event('interruptedDownload');
    let currId;

    chrome.downloads.onChanged.addListener((downloadDelta) => {
        if (downloadDelta.id === currId) {
            if (downloadDelta.state && downloadDelta.state.current === 'complete') {
                document.dispatchEvent(event);
            } else if (downloadDelta.state && downloadDelta.state.current === 'interrupted') {
                console.log(downloadDelta);
                document.dispatchEvent(eventInterrupt);
            }
        }
    });

    downloads.reduce((promise, actual) => {
        return promise.then((last) => (last ? new Promise((resolve) => {
            const { url, filename, destFolder, formName } = actual;
            function listener() {
                document.removeEventListener('finishedDownload', listener);
                document.removeEventListener('interruptedDownload', listener);
                resolve(true);
            };
            function interrupt() {
                document.removeEventListener('finishedDownload', listener);
                document.removeEventListener('interruptedDownload', listener);
                resolve(false);
            }
            console.log(`Processant ${destFolder}, ${formName}: ${url}`);
            document.addEventListener('finishedDownload', listener);
            document.addEventListener('interruptedDownload', interrupt);
            chrome.downloads.download({ url, filename }, (downloadId) => {
                currId = downloadId;
                if (!downloadId) {
                    console.log();
                    console.log('Error downloading...');
                    console.log(runtime.lastError);
                    resolve();
                }
            });
        }) : Promise.resolve(false)));
    }, Promise.resolve(true));
}

chrome.browserAction.onClicked.addListener((/*tab*/) => startDownload());
“严格使用”;
函数startDownload(){
常数formIds={
“此处下载子文件夹”:{
'此处下载文件名':'1-cx-aSAMrTK0IHsQkE…{form id here}',
'此处的另一个文件名':'…-dnqdpnEso{form id here}',
// ...
},
“此处有另一个子文件夹”:{
'此处下载文件名':'1-cx-aSAMrTK0IHsQkE…{form id here}',
'此处的另一个文件名':'…-dnqdpnEso{form id here}',
// ...
},
};
const destFolders=Object.key(formid);
常量下载=[];
for(设t=0,tl=0.length;t{
如果(下载delta.id==currId){
如果(downloadDelta.state&&downloadDelta.state.current==='complete'){
文件、调度事件(事件);
}else if(downloadDelta.state&&downloadDelta.state.current==='interrupted'){
console.log(下载delta);
文件调度事件(eventInterrupt);
}
}
});
下载。减少((承诺,实际)=>{
返回承诺。然后((上次)=>(上次?新承诺((解决)=>{
const{url,filename,destFolder,formName}=actual;
函数侦听器(){
document.removeEventListener('finishedDownload',listener);
document.removeEventListener('interruptedDownload',listener);
决心(正确);
};
函数中断(){
document.removeEventListener('finishedDownload',listener);
document.removeEventListener('interruptedDownload',listener);
决议(假);
}
log(`Processant${destFolder},${formName}:${url}`);
文档。添加了监听器(“finishedDownload”,监听器);
文件。添加的文件列表器(“中断下载”,中断);
chrome.downloads.download({url,filename},(downloaddid)=>{
currId=下载id;
如果(!downloaddid){
console.log();
log('下载错误…');
log(runtime.lastError);
解决();
}
});
}):承诺。解决(错误));
}承诺。决心(真实));
}
chrome.browserAction.onClicked.addListener((/*tab*/)=>startDownload());

我假设您将响应保存到电子表格中,您可以通过使用从工作表中获取值来加快速度。然后创建一个CSV文件,如本Nope中所述,响应不在电子表格中,以加快数据引入。基本上,背后有一个脚本应用程序,可以过滤和关联不同的表单数据,并将其呈现给用户。您可以使用以下链接下载表单响应:
https://docs.google.com/forms/d/{form ID here}/downloadsresponses?tz_offset=-18000000
。通过修改表单ID,这在浏览器中运行良好,但我无法使其与UrlFetchApp一起工作(授权失败),也许您可以找出这一部分。是否可以通过google API访问此链接?我正在尝试从node自动下载响应。jsI并没有使用它,但我认为可以使用表单类item getResponses()](检索响应数组)来代替电子表格类getValues()。那么@JackBrown提到的使用表单类项修改表单类是可能的吗?也许你是说你在这么做。如果效率不高,可以发布代码以寻求帮助。