将 Keenio 数据提取到 google 电子表格中
Extract Keenio Data into google spreadsheet
我目前正在使用 ImportJSON 通过调用 ImportJSON Google Spreadsheet 单元格 Sheet DATA 中的函数。
=ImportJSON("https://api.keen.io/3.0/projects/"& PROJECT_KEY & "/queries/extraction?api_key=" & API_KEY & "&event_collection=" & EVT_COL & "&timezone=" & TIMEZONE & "&latest=" & LATEST & "&property_names..........", PTDATA!$AB)
在 Sheet PTDATA 中,在最后一列单元格中,我为 ImportJSON 设置了一个随机数以重新计算。该函数在 Spreadsheet 打开事件上运行。我还添加了一个自定义菜单来调用 ReCalcCell 自定义函数。
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('IMPORT DATA')
.addItem('KEENIO DATA', 'ReCalcCell')
.addToUi();
}
function ReCalcCell(){
var min = Math.ceil(0);
var max = Math.floor(9999);
var randomNum = Math.floor(Math.random() * (max - min + 1)) + min
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("PTDATA");
sh.getRange("$AB").setValue(randomNum);
}
PTDATA sheet 有特定的列 header 我想从 DATA sheet 中提取数据的名称。在这些列的右侧,我有其他计算列可用于这些特定列。
由于 DATA sheet 中的列总是以随机/打乱的顺序出现,我不得不编写一个小的自定义函数 GCL 接收 header 名称和 return 其数据范围地址 DATA sheet 作为字符串。
function GCL(header,dummy) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("DATA");
var headings = sheet.getRange(1, 1, 1, sheet.getLastColumn()); // get the range representing the whole sheet
var width = headings.getWidth();
var lrow = sheet.getLastRow();
// search every cell in row 1 from A1 till the last column
for (var i = 1; i <= width; i++) {
var data = headings.getCell(1,i).getValue();
if (data == header) {
return ((sheet.getSheetName() + "!" + columnToLetter(i)+"2:" + columnToLetter(i) + lrow).toString()); // return the column range if we find it
break; // exit when found
}
}
return(-1); // return -1 if it doesn't exist
}
function columnToLetter(column)
{
var temp, letter = '';
while (column > 0)
{
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
}
然后我在每个特定列中使用自定义函数 GCL 来获取它的数据范围。填充数据后,PDATA sheet 用于创建不同的数据透视表以用于报告目的。
=ARRAYFORMULA(INDIRECT(GCL(A1,$AB)))
我面临的问题是,尽管导入JSON 数据填充了 DATA sheet:
数据Sheet:
- 列每次都打乱,所以我的计算列无法计算,因为引用消失了。这使枢轴无用!为了解决这个问题,我必须创建 PDATA sheet 以使用 自定义函数 GCL.[=80 拉入特定列=]
- 自定义函数GCL不总是刷新,大部分时间显示#Ref错误.
PDATA Sheet:
顺便说一句,我的 JSON 来自 Keenio 的输出 看起来像这样:
{
"result":
[
{
"sg_event_id": "92-OndRfTs6fZjNdHWzLBw",
"timestamp": 1529618395,
"url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
"ip": "192.168.1.1",
"event": "click",
"keen": {
"timestamp": "2018-06-21T21:59:55.000Z",
"created_at": "2018-06-21T22:00:28.532Z",
"id": "555c1f7c5asdf7000167d87b"
},
"url_offset": {
"index": 38,
"type": "text"
},
"sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
"useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
"email": "no.name@noname.com"
}, {
"sg_event_id": "bjMlfsSfRyuXEVy8LndsYA",
"timestamp": 1529618349,
"url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
"ip": "192.168.1.1",
"event": "click",
"keen": {
"timestamp": "2018-06-21T21:59:09.000Z",
"created_at": "2018-06-21T21:59:39.491Z",
"id": "555c1f7c5asdf7000167d87b"
},
"url_offset": {
"index": 36,
"type": "text"
},
"sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
"useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
"email": "no.name@noname.com"
}, {
"sg_event_id": "fru_s2s1RtueuqBMNoIoTg",
"timestamp": 1529618255,
"url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
"ip": "192.168.1.1",
"event": "click",
"keen": {
"timestamp": "2018-06-21T21:57:35.000Z",
"created_at": "2018-06-21T21:58:20.374Z",
"id": "555c1f7c5asdf7000167d87b"
},
"url_offset": {
"index": 29,
"type": "text"
},
"sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
"useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
"email": "no.name@noname.com"
}
]
}
我的问题是:
- 有没有办法在不使用 ImportJSON 的情况下解析 JSON 结果,它必须作为自定义函数输入到同样依赖于重新计算的单元格中? ImportJSON 有时无法正常工作。
- 如何重构或优化此代码,使其始终可以 return 数据到 PDATA sheet 列?
- 有没有更好的方法来完成我想要的,而不需要借助 PDATA Sheet 中的 GCL 或 DATA sheet 中的 ImportJSON 等自定义函数?
看看您在这里所做的事情,使用 Zapier 集成以 "append-only" 格式设计电子表格可能会容易得多。
Zapier 能够直接处理 SendGrid 事件,并将这些事件附加到您的电子表格中,如果您需要的话。
然后您可以将 "calculation columns" 放在电子表格中单独的 Sheet 上。
只是一个想法。
这个示例脚本怎么样?此脚本使用 UrlFetchApp 解析从 API 检索到的值,并将它们放入 sheet "DATA"。您可以在 spreadsheet 的菜单中 运行 这个。在你运行这个之前,请把端点。
示例脚本:
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('IMPORT DATA')
.addItem('KEENIO DATA', 'ReCalcCell')
.addItem('main', 'main')
.addToUi();
}
function main() {
var url = "###"; // Please put the endpoint with your token.
var res = UrlFetchApp.fetch(url).getContentText(); // Modified
var values = JSON.parse(res);
var putData = values.result.map(function(e) {return [e.useragent, e.sg_event_id, e.timestamp, e.ip, e.url, e.event, e.keen.timestamp, e.keen.created_at, e.keen.id, e.url_offset.index, e.url_offset.type, e.sg_message_id, e.email]});
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("DATA");
sheet.getRange(sheet.getLastRow() + 1, 1, putData.length, putData[0].length).setValues(putData);
}
注:
- 当您使用这个时,请将包含您的令牌的端点放入
url
。
- 我使用你问题中的 JSON 对象确认了这个脚本。所以如果改变了对象的结构,就需要同时修改脚本。请注意这一点。
参考:
如果我对您的问题有误解,请告诉我。我想修改一下。
编辑 1:
模式 1:
var putData = values.result.map(function(e) {return [e.useragent, e.sg_event_id, e.timestamp, e.ip, e.url, e.event, e.keen.timestamp, e.keen.created_at, e.keen.id, JSON.parse(e["url_offset"]).index, JSON.parse(e["url_offset"]).type, e.sg_message_id, e.email]});
模式二:
var putData = values.result.map(function(e) {return [e.useragent, e.sg_event_id, e.timestamp, e.ip, e.url, e.event, e.keen.timestamp, e.keen.created_at, e.keen.id, e["url_offset"].index, e["url_offset"].type, e.sg_message_id, e.email]});
编辑 2:
你能运行这个脚本并提供创建文件的值吗?当然,请删除个人信息。但请不要修改对象的结构。如果你做不到,我想其他办法。
var url = "###"; // Please put the endpoint with your token.
var res = UrlFetchApp.fetch(url).getContentText();
DriveApp.createFile("sample.txt", res, MimeType.PLAIN_TEXT)
编辑 3:
请将此脚本复制并粘贴到您的脚本编辑器 运行 myFunction() 中。然后,请显示文件的值。当你运行此函数时,请确认你的项目中是否存在不相同的函数名称。
function myFunction() {
var url = "###"; // Please put the endpoint with your token.
var res = UrlFetchApp.fetch(url).getContentText();
DriveApp.createFile("sample.txt", res, MimeType.PLAIN_TEXT)
}
编辑 4 :
请将此脚本复制并粘贴到您的脚本编辑器 运行 myFunction2() 中。然后,请展示结果。当你运行此函数时,请确认你的项目中是否存在不相同的函数名称。
请确认 keen
和 url_offset
的键和值是否被检索到。
function myFunction2() {
var url = "###";
var res = UrlFetchApp.fetch(url).getContentText();
var values = JSON.parse(res);
for (var key in values.result[0]) {
Logger.log("key: %s, value: %s", key, values.result[0][key])
if (typeof values.result[0][key] == "object") {
for (var dkey in values.result[0][key]) {
Logger.log("key: %s, dkey: %s, value: %s", key, dkey, values.result[0][key][dkey])
}
}
}
}
编辑 5 :
请将此脚本复制并粘贴到您的脚本编辑器 运行 myFunction3() 中。然后,请展示结果。当你运行此函数时,请确认你的项目中是否存在不相同的函数名称。
function myFunction3() {
var url = "###"; // Please set this.
var res = UrlFetchApp.fetch(url).getContentText();
var values = JSON.parse(res);
var obj = [];
for (var i = 0; i < values.result.length; i++) {
var temp = {};
var v = values.result[i];
for (var key in v) {
temp[key.replace(/_/g, "")] = v[key];
if (typeof v[key] == "object") {
for (var dkey in v[key]) {
temp[key.replace(/_/g, "") + dkey.replace(/_/g, "")] = v[key][dkey];
}
}
}
obj.push(temp);
}
var putData = obj.map(function(e) {return [e.useragent, e.sgeventid, e.timestamp, e.ip, e.url, e.event, e.keentimestamp, e.keencreatedat, e.keenid, e.urloffsetindex, e.urloffsettype, e.sgmessageid, e.email]});
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("DATA");
sheet.getRange(sheet.getLastRow() + 1, 1, putData.length, putData[0].length).setValues(putData);
}
我目前正在使用 ImportJSON 通过调用 ImportJSON Google Spreadsheet 单元格 Sheet DATA 中的函数。
=ImportJSON("https://api.keen.io/3.0/projects/"& PROJECT_KEY & "/queries/extraction?api_key=" & API_KEY & "&event_collection=" & EVT_COL & "&timezone=" & TIMEZONE & "&latest=" & LATEST & "&property_names..........", PTDATA!$AB)
在 Sheet PTDATA 中,在最后一列单元格中,我为 ImportJSON 设置了一个随机数以重新计算。该函数在 Spreadsheet 打开事件上运行。我还添加了一个自定义菜单来调用 ReCalcCell 自定义函数。
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('IMPORT DATA')
.addItem('KEENIO DATA', 'ReCalcCell')
.addToUi();
}
function ReCalcCell(){
var min = Math.ceil(0);
var max = Math.floor(9999);
var randomNum = Math.floor(Math.random() * (max - min + 1)) + min
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("PTDATA");
sh.getRange("$AB").setValue(randomNum);
}
PTDATA sheet 有特定的列 header 我想从 DATA sheet 中提取数据的名称。在这些列的右侧,我有其他计算列可用于这些特定列。
由于 DATA sheet 中的列总是以随机/打乱的顺序出现,我不得不编写一个小的自定义函数 GCL 接收 header 名称和 return 其数据范围地址 DATA sheet 作为字符串。
function GCL(header,dummy) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("DATA");
var headings = sheet.getRange(1, 1, 1, sheet.getLastColumn()); // get the range representing the whole sheet
var width = headings.getWidth();
var lrow = sheet.getLastRow();
// search every cell in row 1 from A1 till the last column
for (var i = 1; i <= width; i++) {
var data = headings.getCell(1,i).getValue();
if (data == header) {
return ((sheet.getSheetName() + "!" + columnToLetter(i)+"2:" + columnToLetter(i) + lrow).toString()); // return the column range if we find it
break; // exit when found
}
}
return(-1); // return -1 if it doesn't exist
}
function columnToLetter(column)
{
var temp, letter = '';
while (column > 0)
{
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
}
然后我在每个特定列中使用自定义函数 GCL 来获取它的数据范围。填充数据后,PDATA sheet 用于创建不同的数据透视表以用于报告目的。
=ARRAYFORMULA(INDIRECT(GCL(A1,$AB)))
我面临的问题是,尽管导入JSON 数据填充了 DATA sheet:
数据Sheet:
- 列每次都打乱,所以我的计算列无法计算,因为引用消失了。这使枢轴无用!为了解决这个问题,我必须创建 PDATA sheet 以使用 自定义函数 GCL.[=80 拉入特定列=]
- 自定义函数GCL不总是刷新,大部分时间显示#Ref错误.
PDATA Sheet:
顺便说一句,我的 JSON 来自 Keenio 的输出 看起来像这样:
{
"result":
[
{
"sg_event_id": "92-OndRfTs6fZjNdHWzLBw",
"timestamp": 1529618395,
"url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
"ip": "192.168.1.1",
"event": "click",
"keen": {
"timestamp": "2018-06-21T21:59:55.000Z",
"created_at": "2018-06-21T22:00:28.532Z",
"id": "555c1f7c5asdf7000167d87b"
},
"url_offset": {
"index": 38,
"type": "text"
},
"sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
"useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
"email": "no.name@noname.com"
}, {
"sg_event_id": "bjMlfsSfRyuXEVy8LndsYA",
"timestamp": 1529618349,
"url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
"ip": "192.168.1.1",
"event": "click",
"keen": {
"timestamp": "2018-06-21T21:59:09.000Z",
"created_at": "2018-06-21T21:59:39.491Z",
"id": "555c1f7c5asdf7000167d87b"
},
"url_offset": {
"index": 36,
"type": "text"
},
"sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
"useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
"email": "no.name@noname.com"
}, {
"sg_event_id": "fru_s2s1RtueuqBMNoIoTg",
"timestamp": 1529618255,
"url": "https://noname.com?utm_campaign=website&utm_source=sendgrid.com&utm_medium=email",
"ip": "192.168.1.1",
"event": "click",
"keen": {
"timestamp": "2018-06-21T21:57:35.000Z",
"created_at": "2018-06-21T21:58:20.374Z",
"id": "555c1f7c5asdf7000167d87b"
},
"url_offset": {
"index": 29,
"type": "text"
},
"sg_message_id": "F5mwV1rESdyKFA_2bn1IEQ.filter0042p3las1-15933-5B2A68E8-36.0",
"useragent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)",
"email": "no.name@noname.com"
}
]
}
我的问题是:
- 有没有办法在不使用 ImportJSON 的情况下解析 JSON 结果,它必须作为自定义函数输入到同样依赖于重新计算的单元格中? ImportJSON 有时无法正常工作。
- 如何重构或优化此代码,使其始终可以 return 数据到 PDATA sheet 列?
- 有没有更好的方法来完成我想要的,而不需要借助 PDATA Sheet 中的 GCL 或 DATA sheet 中的 ImportJSON 等自定义函数?
看看您在这里所做的事情,使用 Zapier 集成以 "append-only" 格式设计电子表格可能会容易得多。
Zapier 能够直接处理 SendGrid 事件,并将这些事件附加到您的电子表格中,如果您需要的话。
然后您可以将 "calculation columns" 放在电子表格中单独的 Sheet 上。
只是一个想法。
这个示例脚本怎么样?此脚本使用 UrlFetchApp 解析从 API 检索到的值,并将它们放入 sheet "DATA"。您可以在 spreadsheet 的菜单中 运行 这个。在你运行这个之前,请把端点。
示例脚本:
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('IMPORT DATA')
.addItem('KEENIO DATA', 'ReCalcCell')
.addItem('main', 'main')
.addToUi();
}
function main() {
var url = "###"; // Please put the endpoint with your token.
var res = UrlFetchApp.fetch(url).getContentText(); // Modified
var values = JSON.parse(res);
var putData = values.result.map(function(e) {return [e.useragent, e.sg_event_id, e.timestamp, e.ip, e.url, e.event, e.keen.timestamp, e.keen.created_at, e.keen.id, e.url_offset.index, e.url_offset.type, e.sg_message_id, e.email]});
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("DATA");
sheet.getRange(sheet.getLastRow() + 1, 1, putData.length, putData[0].length).setValues(putData);
}
注:
- 当您使用这个时,请将包含您的令牌的端点放入
url
。 - 我使用你问题中的 JSON 对象确认了这个脚本。所以如果改变了对象的结构,就需要同时修改脚本。请注意这一点。
参考:
如果我对您的问题有误解,请告诉我。我想修改一下。
编辑 1:
模式 1:
var putData = values.result.map(function(e) {return [e.useragent, e.sg_event_id, e.timestamp, e.ip, e.url, e.event, e.keen.timestamp, e.keen.created_at, e.keen.id, JSON.parse(e["url_offset"]).index, JSON.parse(e["url_offset"]).type, e.sg_message_id, e.email]});
模式二:
var putData = values.result.map(function(e) {return [e.useragent, e.sg_event_id, e.timestamp, e.ip, e.url, e.event, e.keen.timestamp, e.keen.created_at, e.keen.id, e["url_offset"].index, e["url_offset"].type, e.sg_message_id, e.email]});
编辑 2:
你能运行这个脚本并提供创建文件的值吗?当然,请删除个人信息。但请不要修改对象的结构。如果你做不到,我想其他办法。
var url = "###"; // Please put the endpoint with your token.
var res = UrlFetchApp.fetch(url).getContentText();
DriveApp.createFile("sample.txt", res, MimeType.PLAIN_TEXT)
编辑 3:
请将此脚本复制并粘贴到您的脚本编辑器 运行 myFunction() 中。然后,请显示文件的值。当你运行此函数时,请确认你的项目中是否存在不相同的函数名称。
function myFunction() {
var url = "###"; // Please put the endpoint with your token.
var res = UrlFetchApp.fetch(url).getContentText();
DriveApp.createFile("sample.txt", res, MimeType.PLAIN_TEXT)
}
编辑 4 :
请将此脚本复制并粘贴到您的脚本编辑器 运行 myFunction2() 中。然后,请展示结果。当你运行此函数时,请确认你的项目中是否存在不相同的函数名称。
请确认 keen
和 url_offset
的键和值是否被检索到。
function myFunction2() {
var url = "###";
var res = UrlFetchApp.fetch(url).getContentText();
var values = JSON.parse(res);
for (var key in values.result[0]) {
Logger.log("key: %s, value: %s", key, values.result[0][key])
if (typeof values.result[0][key] == "object") {
for (var dkey in values.result[0][key]) {
Logger.log("key: %s, dkey: %s, value: %s", key, dkey, values.result[0][key][dkey])
}
}
}
}
编辑 5 :
请将此脚本复制并粘贴到您的脚本编辑器 运行 myFunction3() 中。然后,请展示结果。当你运行此函数时,请确认你的项目中是否存在不相同的函数名称。
function myFunction3() {
var url = "###"; // Please set this.
var res = UrlFetchApp.fetch(url).getContentText();
var values = JSON.parse(res);
var obj = [];
for (var i = 0; i < values.result.length; i++) {
var temp = {};
var v = values.result[i];
for (var key in v) {
temp[key.replace(/_/g, "")] = v[key];
if (typeof v[key] == "object") {
for (var dkey in v[key]) {
temp[key.replace(/_/g, "") + dkey.replace(/_/g, "")] = v[key][dkey];
}
}
}
obj.push(temp);
}
var putData = obj.map(function(e) {return [e.useragent, e.sgeventid, e.timestamp, e.ip, e.url, e.event, e.keentimestamp, e.keencreatedat, e.keenid, e.urloffsetindex, e.urloffsettype, e.sgmessageid, e.email]});
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("DATA");
sheet.getRange(sheet.getLastRow() + 1, 1, putData.length, putData[0].length).setValues(putData);
}