【问题标题】:Going from an array to object and creating subclasses从数组到对象并创建子类
【发布时间】:2021-10-23 12:27:38
【问题描述】:

我是 google app 脚本的初学者,想问一个问题,关于如何根据从我的电子表格中提取的信息数组为对象创建子类。

这是一个示例sheet,其中包含“历史”工作表中的一些数据。输入数据是用户投资的交易历史。我的最终目标是在 google app 脚本中创建一个数组,其中包含任何给定股票的调整后的股票分割值。

但是,我的项目的第一步是以我可以执行这些计算的方式收集数据。为此,我需要创建一个像这样的对象:

stock symbol: {date:value, {quantity: value, price:value}}, {date:value, {split ratio:value}}

这是因为在此对象中,日期与数量价格和拆分比率相关联。在以后的计算中,我会查看拆分值的日期是否小于或等于数量/价格值的日期,如果是这样,则执行拆分比率 * 数量和价格/拆分比率。如果这不是真的,那么对于任何给定的库存,保持价格和数量不变。最后以与原始数组相同的形式返回这些对象。

这是我到目前为止所做的尝试:

function createDate(date, quantity, price) {
  this.date = date;
  this.quantityPrice = new createDateData (quantity, price);
}

function createDateData(quantity, price) {
  this.quantity = quantity;
  this.price = price;
}

function retrieveData () {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const inputSheet = ss.getSheetByName('History');
  const data = inputSheet.getRange(2, 1, inputSheet.getLastRow() - 1, 9).getValues();
  const filterd = data.filter(row => row[2] == 'Buy' || row[2] == 'Sell' || row [2] == 'Split');
  const sorted = filterd.sort((a, b) => {
    if (a[0] < b[0]) return -1
    if (a[0] > b[0]) return 1
    else return 0
  })
 for ( let i of sorted) {
var sampleData= new createDate([i][0][0],[i][0][3],[i][0][4]);
console.log(sampleData);
 }
}

这是我得到的输出

    { date: Tue Jun 30 2020 18:00:00 GMT-0400 (Eastern Daylight Time),
  quantityPrice: { quantity: 1, price: 40000 } }

与期望的输出有什么不同?

问题:如何获得所需的输出?以 AMZN 为例:

AMZN: {9/28/2020, {1, 100}}, {9/28/2020, {0.5, 200}}, {10/19/2020 {0.2, 100}}, {11/27/2020, {10}}

EDIT2:有关所需输出,请参阅工作表“所需输出”。

【问题讨论】:

  • 我必须为我糟糕的英语水平道歉。关于Question: How do I get the desired output?,什么是stock symbol: {date:value, {quantity: value, price:value}}, {date:value, {split ratio:value}}?那是字符串值?我可以问你目标的细节吗?
  • 感谢您的回复,我编辑了问题以显示所需的输出。见编辑。
  • 感谢您的回复。我不得不为我糟糕的英语水平道歉。不幸的是,来自Question: How do I get the desired output? For example, in the case of AMZN:,我无法理解您的目标。因为我认为AMZN: {9/28/2020, {1, 100}}, {9/28/2020, {0.5, 200}}, {10/19/2020 {0.2, 100}}, {11/27/2020, {10}} 不是JSON 对象。您想将其作为文本值检索吗?我为我的理解不佳道歉。
  • 抱歉,如果这不是一个对象。如果数量和价格的日期等于或小于拆分比率的日期,我希望将数量*拆分比率和价格/拆分比率相乘。那我该怎么做呢?
  • @YuriKhristich 所以我按照你的建议添加了一张“期望的输出”表。您可以看到 AMZN 的数量乘以 10,每股价格除以 10。这是针对拆分前的所有交易进行的,而不是拆分后的交易。数字 10 来自单元格 I28 中的分流比。这个想法是制作一个动态脚本,这次是 AMZN,但下一次可能是不同的股票。我希望我现在解释得足够好。

标签: arrays object google-apps-script google-sheets


【解决方案1】:

据我所知,“价格”列中有数组公式,因此您只需更新“数量”列。 “价格”列将自动更新。

你确定你想要的输出中的第 27 行应该改变吗?我认为不应该,因为它是“Cash”,而不是“AMZN”。

试试这个代码:

function main() {
  var ss    = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('History');
  var range = sheet.getRange(3,1,sheet.getLastRow(),9);
  var data  = range.getValues().reverse(); // reverse to iterate it from the top to the bottom

  for (var row in data) {
    var action = data[row][2];
    if (action != 'Split') continue;
    data = [...data.slice(0,row), ...update(data.slice(row))]; // update all rows below the 'Split' 
  }

  // get column 'Quantity' from the data and put it on the sheet
  var quantity = data.map(x => [x[3]]).reverse(); 
  sheet.getRange(3,4,data.length,1).setValues(quantity);
}


// the function takes rows, recalculates quantity and returns the updated rows

function update(data) {
  var security = data[0][1];
  var ratio    = data[0][8];

  // if the security is the same as in the first row,
  // and if the action is 'Buy' or 'Sell':
  // the price will be multiply by the ratio
  for (var row in data) {
    if (data[row][1] != security) continue;
    var action = data[row][2];
    if (['Buy','Sell'].includes(action)) data[row][3] *= ratio;
    try {if (row[+r+1][1] == 'Split') break} catch(e) {} // <-- updated line
  }

  return data;
}

脚本暗示所有行都按日期排序。最新日期在底部,最旧日期在顶部。

没有任何对象。我认为不需要他们。也许它可以用另一种方式完成,用对象。

【讨论】:

  • 感谢您教我花时间编写此脚本。它完美无缺!我试图检查稳健性,例如,如果 AMZN 在第一次股票分割后的晚些时候进行股票分割会发生什么?我编辑了原始数据和所需的输出。但是,您的脚本采用最新的拆分比率,然后将所有数量与该比率相乘。但是,如果有 2 次股票拆分,第一个比率必须适用于所有股票,直到股票拆分日期,第二个比率适用于该日期之后的所有股票拆分,等等。是否也可以对此进行编程?
  • '但是如果有 2 次股票拆分...' 那么这是一个新条件。当然可以处理。我会尽快更新代码。可能它只会在代码中多写一行:如果下一行包含'Split',则在if (['Buy','Sell']... 行之后打破循环
  • 你可以自己尝试一下:添加try {if (row[+r+1][1] == 'Split') break} catch(e) {}这一行看看。我不在我的桌面上,我现在无法测试它。 try/catch 是必需的,因为它可以是最后一行,并且不会有 nex (r+1) 行。
  • 非常感谢您的努力。明天会尝试你的建议。女儿病了儿子今天我的手被绑了。
  • 我刚刚尝试了更新的线路,看起来它确实有效。祝孩子早日康复,一切安好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 2019-09-18
  • 2020-01-26
  • 2021-12-06
相关资源
最近更新 更多