如何将 Google 工作表中的数据放入网络应用程序中的时间轴

How to put data from Google Sheets to Timeline in web app

我想根据 "TimeLineData" sheet 中的数据制作时间线图表。这些数据有时会发生变化,所以我想让它动态化。我不确定您是否可以使用常规图表实现它,所以我尝试使用我在 google 文档中找到的脚本,然后从@WhiteHat 那里获得了帮助。

在数据中 sheet 该项目不需要 D 和 E 列。只有彩色列。 正如您在图片中看到的,我想按机器对订单进行分组,并查看生产结束前的剩余时间。 F 列显示剩余时间(以分钟为单位)。我还为开始日期 H2 和 I2 添加了额外的单元格。 从左边开始应该是离“发货”日期最近的订单

所以我的问题是:

  1. 如何向左移动数据?如上图所示。我想为一行中的所有第一个值设置相同的起点,然后添加下一个时间值。我试过 '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

中的宽度