如何将 Google 工作表中的数据放入网络应用程序中的时间轴
How to put data from Google Sheets to Timeline in web app
我想根据 "TimeLineData" sheet 中的数据制作时间线图表。这些数据有时会发生变化,所以我想让它动态化。我不确定您是否可以使用常规图表实现它,所以我尝试使用我在 google 文档中找到的脚本,然后从@WhiteHat 那里获得了帮助。
在数据中 sheet 该项目不需要 D 和 E 列。只有彩色列。
正如您在图片中看到的,我想按机器对订单进行分组,并查看生产结束前的剩余时间。 F 列显示剩余时间(以分钟为单位)。我还为开始日期 H2 和 I2 添加了额外的单元格。
从左边开始应该是离“发货”日期最近的订单
所以我的问题是:
- 如何向左移动数据?如上图所示。我想为一行中的所有第一个值设置相同的起点,然后添加下一个时间值。我试过 'promise()' 但没成功。
这就是我现在得到的:
任何建议都会有所帮助!
如果有什么不清楚的地方,请告诉我
@WhiteHat提供的代码:
// load google charts
google.charts.load('current', {
packages:['timeline']
}).then(function () {
// get ss data
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1SaGo-yA6YPP-Um68Sgm8H3yMyfqXclDQWl5_l4cxgs4/gviz/tq?gid=0&headers=1&sheet=TimelineData');
query.send(function (response) {
// build data table - ss
var dataSS = response.getDataTable();
// sort by machine, delivery date, order #
dataSS.sort([{
column: getColumnIndex('Machine', dataSS)
}, {
column: getColumnIndex('Out for Delivery', dataSS)
}, {
column: getColumnIndex('Order NO', dataSS)
}]);
// build data table - timeline
var dataTimeline = new google.visualization.DataTable();
dataTimeline.addColumn('string', 'Machine');
dataTimeline.addColumn('string', 'Order NO');
dataTimeline.addColumn('date', 'Start');
dataTimeline.addColumn('date', 'End');
// get overall start date & time
var startDate = dataSS.getColumnRange(getColumnIndex('start date', dataSS)).min;
var startTime = dataSS.getColumnRange(getColumnIndex('start time', dataSS)).min;
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
startTime.forEach(function (timeSegment, index) {
// determine time segment
var milliseconds;
switch (index) {
// hours
case 0:
milliseconds = 1000 * 60 * 60 * timeSegment;
break;
// minutes
case 1:
milliseconds = 1000 * 60 * timeSegment;
break;
// seconds
case 2:
milliseconds = 1000 * timeSegment;
break;
// milliseconds
case 3:
milliseconds = timeSegment;
break;
}
// add milliseconds to start date
startDate = new Date(startDate.getTime() + milliseconds);
});
// process rows
var endDate;
var minutesProcess;
var minutesTotal = 0;
for (var row = 0; row < dataSS.getNumberOfRows(); row++) {
// calculate minutes processed and end date
minutesProcess = dataSS.getValue(row, getColumnIndex('Production Time Left', dataSS));
minutesTotal += minutesProcess;
endDate = new Date(startDate.getTime() + (1000 * 60 * minutesProcess));
// add row
dataTimeline.addRow([
dataSS.getValue(row, getColumnIndex('Machine', dataSS)),
dataSS.getValue(row, getColumnIndex('Order NO', dataSS)),
startDate,
endDate
]);
// determine if 8 hours has passed
if ((minutesTotal / 60) >= 8) {
// increment day until not the weekend
do {
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 1, 8);
} while ((startDate.getDate() === 0) || (startDate.getDate() === 6));
} else {
startDate = endDate;
}
}
// determine chart height
var rowHeight = 42;
var options = {
height: (dataTimeline.getNumberOfRows() * rowHeight) + rowHeight
};
// draw chart
var chart = new google.visualization.Timeline(document.getElementById('timeline'));
chart.draw(dataTimeline, options);
window.addEventListener('resize', function () {
chart.draw(dataTimeline, options);
});
});
// get data table column index by column label
function getColumnIndex(label, dataTable) {
// loop columns until column label is found
for (var i = 0; i < dataTable.getNumberOfColumns(); i++) {
if (label === dataTable.getColumnLabel(i)) {
return i;
}
}
// label not found
return -1;
}
});
获取数据到页面供图表使用,
我们可以使用 Query
class.
将查询设置和工作表名称附加到电子表格的末尾 url...
/gviz/tq?gid=0&headers=1&sheet=TimelineData
使用查询class获取数据并等待响应。
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1SaGo-yA6YPP-Um68Sgm8H3yMyfqXclDQWl5_l4cxgs4/gviz/tq?gid=0&headers=1&sheet=TimelineData');
query.send(function (response) {
// build data table - ss
var dataSS = response.getDataTable();
...
然后我们需要处理每一行,以便为每个流程构建开始和结束日期。
首先,对电子表格数据进行排序...
// sort by machine, delivery date, order #
dataSS.sort([{
column: getColumnIndex('Machine', dataSS)
}, {
column: getColumnIndex('Out for Delivery', dataSS)
}, {
column: getColumnIndex('Order NO', dataSS)
}]);
然后为时间线构建数据table...
// build data table - timeline
var dataTimeline = new google.visualization.DataTable();
dataTimeline.addColumn('string', 'Machine');
dataTimeline.addColumn('string', 'Order NO');
dataTimeline.addColumn('date', 'Start');
dataTimeline.addColumn('date', 'End');
然后我们需要获取整体开始日期和时间。
我们可以使用数据 table 方法 --> getColumnRange(columnIndex)
这将 return 我们指定的列的最小值和最大值。
在这种情况下,我们将使用最小值。
// get overall start date & time
var startDate = dataSS.getColumnRange(getColumnIndex('start date', dataSS)).min;
var startTime = dataSS.getColumnRange(getColumnIndex('start time', dataSS)).min;
然后我们从开始日期中删除任何时间部分。
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
开始时间列的格式将为 timeofday
它将是一个包含四个数字的数组 --> [hours, minutes, seconds, milliseconds]
然后我们将开始时间添加到开始日期。
startTime.forEach(function (timeSegment, index) {
// determine time segment
var milliseconds;
switch (index) {
// hours
case 0:
milliseconds = 1000 * 60 * 60 * timeSegment;
break;
// minutes
case 1:
milliseconds = 1000 * 60 * timeSegment;
break;
// seconds
case 2:
milliseconds = 1000 * timeSegment;
break;
// milliseconds
case 3:
milliseconds = timeSegment;
break;
}
// add milliseconds to start date
startDate = new Date(startDate.getTime() + milliseconds);
});
然后我们处理电子表格中的行。
首先,计算该行的处理分钟数并计算结束日期。
为时间轴添加数据 table 行。
最后判断是否过了8小时
如果是,移至下一个工作日,否则,使用结束日期作为下一个开始日期。
// process rows
var endDate;
var minutesProcess;
var minutesTotal = 0;
for (var row = 0; row < dataSS.getNumberOfRows(); row++) {
// calculate minutes processed and end date
minutesProcess = dataSS.getValue(row, getColumnIndex('Production Time Left', dataSS));
minutesTotal += minutesProcess;
endDate = new Date(startDate.getTime() + (1000 * 60 * minutesProcess));
// add row
dataTimeline.addRow([
dataSS.getValue(row, getColumnIndex('Machine', dataSS)),
dataSS.getValue(row, getColumnIndex('Order NO', dataSS)),
startDate,
endDate
]);
// determine if 8 hours has passed
if ((minutesTotal / 60) >= 8) {
// increment day until not the weekend
do {
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 1, 8);
} while ((startDate.getDate() === 0) || (startDate.getDate() === 6));
} else {
startDate = endDate;
}
}
计算图表高度,绘制图表...
// determine chart height
var rowHeight = 42;
var options = {
height: (dataTimeline.getNumberOfRows() * rowHeight) + rowHeight
};
// draw chart
var chart = new google.visualization.Timeline(document.getElementById('timeline'));
chart.draw(dataTimeline, options);
window.addEventListener('resize', function () {
chart.draw(dataTimeline, options);
});
有关工作示例,请参阅以下 fiddle...
https://jsfiddle.net/WhiteHat/cthqur2o/10/
注意:图表默认会填满屏幕宽度,
您可能需要增加 options
中的宽度
我想根据 "TimeLineData" sheet 中的数据制作时间线图表。这些数据有时会发生变化,所以我想让它动态化。我不确定您是否可以使用常规图表实现它,所以我尝试使用我在 google 文档中找到的脚本,然后从@WhiteHat 那里获得了帮助。
在数据中 sheet 该项目不需要 D 和 E 列。只有彩色列。 正如您在图片中看到的,我想按机器对订单进行分组,并查看生产结束前的剩余时间。 F 列显示剩余时间(以分钟为单位)。我还为开始日期 H2 和 I2 添加了额外的单元格。 从左边开始应该是离“发货”日期最近的订单
所以我的问题是:
- 如何向左移动数据?如上图所示。我想为一行中的所有第一个值设置相同的起点,然后添加下一个时间值。我试过 'promise()' 但没成功。
这就是我现在得到的:
任何建议都会有所帮助! 如果有什么不清楚的地方,请告诉我
@WhiteHat提供的代码:
// load google charts
google.charts.load('current', {
packages:['timeline']
}).then(function () {
// get ss data
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1SaGo-yA6YPP-Um68Sgm8H3yMyfqXclDQWl5_l4cxgs4/gviz/tq?gid=0&headers=1&sheet=TimelineData');
query.send(function (response) {
// build data table - ss
var dataSS = response.getDataTable();
// sort by machine, delivery date, order #
dataSS.sort([{
column: getColumnIndex('Machine', dataSS)
}, {
column: getColumnIndex('Out for Delivery', dataSS)
}, {
column: getColumnIndex('Order NO', dataSS)
}]);
// build data table - timeline
var dataTimeline = new google.visualization.DataTable();
dataTimeline.addColumn('string', 'Machine');
dataTimeline.addColumn('string', 'Order NO');
dataTimeline.addColumn('date', 'Start');
dataTimeline.addColumn('date', 'End');
// get overall start date & time
var startDate = dataSS.getColumnRange(getColumnIndex('start date', dataSS)).min;
var startTime = dataSS.getColumnRange(getColumnIndex('start time', dataSS)).min;
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
startTime.forEach(function (timeSegment, index) {
// determine time segment
var milliseconds;
switch (index) {
// hours
case 0:
milliseconds = 1000 * 60 * 60 * timeSegment;
break;
// minutes
case 1:
milliseconds = 1000 * 60 * timeSegment;
break;
// seconds
case 2:
milliseconds = 1000 * timeSegment;
break;
// milliseconds
case 3:
milliseconds = timeSegment;
break;
}
// add milliseconds to start date
startDate = new Date(startDate.getTime() + milliseconds);
});
// process rows
var endDate;
var minutesProcess;
var minutesTotal = 0;
for (var row = 0; row < dataSS.getNumberOfRows(); row++) {
// calculate minutes processed and end date
minutesProcess = dataSS.getValue(row, getColumnIndex('Production Time Left', dataSS));
minutesTotal += minutesProcess;
endDate = new Date(startDate.getTime() + (1000 * 60 * minutesProcess));
// add row
dataTimeline.addRow([
dataSS.getValue(row, getColumnIndex('Machine', dataSS)),
dataSS.getValue(row, getColumnIndex('Order NO', dataSS)),
startDate,
endDate
]);
// determine if 8 hours has passed
if ((minutesTotal / 60) >= 8) {
// increment day until not the weekend
do {
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 1, 8);
} while ((startDate.getDate() === 0) || (startDate.getDate() === 6));
} else {
startDate = endDate;
}
}
// determine chart height
var rowHeight = 42;
var options = {
height: (dataTimeline.getNumberOfRows() * rowHeight) + rowHeight
};
// draw chart
var chart = new google.visualization.Timeline(document.getElementById('timeline'));
chart.draw(dataTimeline, options);
window.addEventListener('resize', function () {
chart.draw(dataTimeline, options);
});
});
// get data table column index by column label
function getColumnIndex(label, dataTable) {
// loop columns until column label is found
for (var i = 0; i < dataTable.getNumberOfColumns(); i++) {
if (label === dataTable.getColumnLabel(i)) {
return i;
}
}
// label not found
return -1;
}
});
获取数据到页面供图表使用,
我们可以使用 Query
class.
将查询设置和工作表名称附加到电子表格的末尾 url...
/gviz/tq?gid=0&headers=1&sheet=TimelineData
使用查询class获取数据并等待响应。
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1SaGo-yA6YPP-Um68Sgm8H3yMyfqXclDQWl5_l4cxgs4/gviz/tq?gid=0&headers=1&sheet=TimelineData');
query.send(function (response) {
// build data table - ss
var dataSS = response.getDataTable();
...
然后我们需要处理每一行,以便为每个流程构建开始和结束日期。
首先,对电子表格数据进行排序...
// sort by machine, delivery date, order #
dataSS.sort([{
column: getColumnIndex('Machine', dataSS)
}, {
column: getColumnIndex('Out for Delivery', dataSS)
}, {
column: getColumnIndex('Order NO', dataSS)
}]);
然后为时间线构建数据table...
// build data table - timeline
var dataTimeline = new google.visualization.DataTable();
dataTimeline.addColumn('string', 'Machine');
dataTimeline.addColumn('string', 'Order NO');
dataTimeline.addColumn('date', 'Start');
dataTimeline.addColumn('date', 'End');
然后我们需要获取整体开始日期和时间。
我们可以使用数据 table 方法 --> getColumnRange(columnIndex)
这将 return 我们指定的列的最小值和最大值。
在这种情况下,我们将使用最小值。
// get overall start date & time
var startDate = dataSS.getColumnRange(getColumnIndex('start date', dataSS)).min;
var startTime = dataSS.getColumnRange(getColumnIndex('start time', dataSS)).min;
然后我们从开始日期中删除任何时间部分。
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
开始时间列的格式将为 timeofday
它将是一个包含四个数字的数组 --> [hours, minutes, seconds, milliseconds]
然后我们将开始时间添加到开始日期。
startTime.forEach(function (timeSegment, index) {
// determine time segment
var milliseconds;
switch (index) {
// hours
case 0:
milliseconds = 1000 * 60 * 60 * timeSegment;
break;
// minutes
case 1:
milliseconds = 1000 * 60 * timeSegment;
break;
// seconds
case 2:
milliseconds = 1000 * timeSegment;
break;
// milliseconds
case 3:
milliseconds = timeSegment;
break;
}
// add milliseconds to start date
startDate = new Date(startDate.getTime() + milliseconds);
});
然后我们处理电子表格中的行。
首先,计算该行的处理分钟数并计算结束日期。
为时间轴添加数据 table 行。
最后判断是否过了8小时
如果是,移至下一个工作日,否则,使用结束日期作为下一个开始日期。
// process rows
var endDate;
var minutesProcess;
var minutesTotal = 0;
for (var row = 0; row < dataSS.getNumberOfRows(); row++) {
// calculate minutes processed and end date
minutesProcess = dataSS.getValue(row, getColumnIndex('Production Time Left', dataSS));
minutesTotal += minutesProcess;
endDate = new Date(startDate.getTime() + (1000 * 60 * minutesProcess));
// add row
dataTimeline.addRow([
dataSS.getValue(row, getColumnIndex('Machine', dataSS)),
dataSS.getValue(row, getColumnIndex('Order NO', dataSS)),
startDate,
endDate
]);
// determine if 8 hours has passed
if ((minutesTotal / 60) >= 8) {
// increment day until not the weekend
do {
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 1, 8);
} while ((startDate.getDate() === 0) || (startDate.getDate() === 6));
} else {
startDate = endDate;
}
}
计算图表高度,绘制图表...
// determine chart height
var rowHeight = 42;
var options = {
height: (dataTimeline.getNumberOfRows() * rowHeight) + rowHeight
};
// draw chart
var chart = new google.visualization.Timeline(document.getElementById('timeline'));
chart.draw(dataTimeline, options);
window.addEventListener('resize', function () {
chart.draw(dataTimeline, options);
});
有关工作示例,请参阅以下 fiddle...
https://jsfiddle.net/WhiteHat/cthqur2o/10/
注意:图表默认会填满屏幕宽度,
您可能需要增加 options