导入时,查找并替换重复的,或者没有重复的,粘贴在数据集的底部

When importing, find and replace the duplicate, or if there is no duplicate, paste at the bottom of the data set

我正在尝试编译一个包含财务信息的数据库。为此,我需要使用搜索最后一个空行并将数据粘贴到那里的脚本将每只股票 'ticker' 的新数据导入数据库。

但是,如果股票有可用的新数据,我想将其粘贴到数据库中的旧数据上 - 以避免重复。如果没有重复项继续使用原始脚本将其粘贴到下一个可用行。

我想我只需要调整我当前的脚本,为 API ImporterTest!C2[ 的任何匹配项添加 查找和替换 =30=] 和 Column DatabaseTest!H:H 中的代码,如果要将下面脚本中的范围粘贴到它上面,以及如果没有匹配项的 IF 函数继续原来的脚本。

这是我目前使用的脚本:

//set spreadsheet and sheets
  const spreadsheet = SpreadsheetApp.getActive();
  const importerSheet = spreadsheet.getSheetByName('API ImporterTest');
  const databaseSheet = spreadsheet.getSheetByName('DatabaseTest');

//cash flow
  const lastRowColumnValuesCash = databaseSheet.getRange("G:G").getValues()
  const lastRowIndexCash = lastRowColumnValuesCash.length - lastRowColumnValuesCash.reverse()
    .findIndex(row => row[0] !== '');
//income statement
  const lastRowColumnValuesIncome = databaseSheet.getRange("AT:AT").getValues()
  const lastRowIndexIncome = lastRowColumnValuesIncome.length - lastRowColumnValuesIncome.reverse()
    .findIndex(row => row[0] !== '');
//balance sheet
  const lastRowColumnValuesBalance = databaseSheet.getRange("CC:CC").getValues()
  const lastRowIndexBalance = lastRowColumnValuesBalance.length - lastRowColumnValuesBalance.reverse()
    .findIndex(row => row[0] !== '');
//fundamentals
  const lastRowColumnValuesFund = databaseSheet.getRange("DY:DY").getValues()
  const lastRowIndexFund = lastRowColumnValuesFund.length - lastRowColumnValuesFund.reverse()
    .findIndex(row => row[0] !== '');
//keymetrics
  const lastRowColumnValuesMet = databaseSheet.getRange("GE:GE").getValues()
  const lastRowIndexMet = lastRowColumnValuesMet.length - lastRowColumnValuesMet.reverse()
    .findIndex(row => row[0] !== '');
//profile
  const lastRowColumnValuesProf = databaseSheet.getRange("IN:IN").getValues()
  const lastRowIndexProf = lastRowColumnValuesProf.length - lastRowColumnValuesProf.reverse()
    .findIndex(row => row[0] !== '');

//run
  if (databaseSheet.getLastRow() + 15 > databaseSheet.getMaxRows())
    databaseSheet.insertRowsAfter(databaseSheet.getMaxRows(),
      databaseSheet.getLastRow() + 15 - databaseSheet.getMaxRows()
    )
    importerSheet
    .getRange('F3:J40')
    .copyTo(
      databaseSheet.getRange(`G${lastRowIndexCash + 1}`),
      SpreadsheetApp.CopyPasteType.PASTE_VALUES,
      true
    );
  importerSheet
    .getRange('S3:W36')
    .copyTo(
      databaseSheet.getRange(`AT${lastRowIndexIncome + 1}`),
      SpreadsheetApp.CopyPasteType.PASTE_VALUES,
      true
    );
  importerSheet
    .getRange('AF3:AJ49')
    .copyTo(
      databaseSheet.getRange(`CC${lastRowIndexBalance + 1}`),
      SpreadsheetApp.CopyPasteType.PASTE_VALUES,
      true 
      );
    importerSheet
    .getRange('AS3:AW59')
    .copyTo(
      databaseSheet.getRange(`DY${lastRowIndexFund + 1}`),
      SpreadsheetApp.CopyPasteType.PASTE_VALUES,
      true
    );
    importerSheet
    .getRange('BF3:BJ62')
    .copyTo(
      databaseSheet.getRange(`GE${lastRowIndexMet + 1}`),
      SpreadsheetApp.CopyPasteType.PASTE_VALUES,
      true
    );
    importerSheet
    .getRange('BS3:BW36')
    .copyTo(
      databaseSheet.getRange(`IN${lastRowIndexProf + 1}`),
      SpreadsheetApp.CopyPasteType.PASTE_VALUES,
      true
    );
};

这是一个功能测试 Sheet,用于使用示例解决方案对其进行测试(要生成新的数据集进行测试,请将 'API Importer Test' 中的单元格 'C2' 更改为另一个代码,FB , AAPL, GME 例如并点击导入。)

https://docs.google.com/spreadsheets/d/1UPAz7ku_AILB9aDvKCVyClvBh_5XskGPgGh0w784PR4/edit?usp=sharing

An Example of the 2 Solutions - Note this sheet was for visualization of the logic only, so the current script would not work on these cells.

解决方案:

在我看来,检索这么多 lastRow 索引没有意义。这是sheetDatabase里面的索引,如果没有发现重复的ticker应该写入数据,所有这些lastRow索引应该是相同的。至少在您提供的示例中,所有这些索引都是一致的。

考虑到这一点,我将执行以下操作:

  • 检查第 G 列的最后一行(因为我猜如果填充了该行,日期将始终被填充)。
  • API ImporterTest!B3 中检索对应于导入代码的值。
  • 检索Database中的所有当前tickers,当前在C3中,用filter过滤空行。
  • 检查要导入的代码是否在当前代码中,如果是,它位于什么索引中。您可以为此使用 indexOf
  • 检索 rowIndex 将数据写入的位置,这取决于上一步的索引是否为 -1(找到重复项),并考虑到数据从第 3 行开始,每次都有 5 个合并单元格,所以 5 个值中有 4 个是空的,因此被过滤掉了。因此,如果发现重复,rowIndex 应该是 index * 5 + 3。我在下面的示例中使用 ternary operator 来做到这一点:const rowIndex = index !== -1 ? index * 5 + 3 : lastRowIndexCash + 1;
  • 将所有不同的范围复制到相同的 rowIndex,因为您要将所有数据写入相同的行。

代码示例:

const moveValuesOnly = () => {
  const spreadsheet = SpreadsheetApp.getActive();
  const importerSheet = spreadsheet.getSheetByName('API ImporterTest');
  const databaseSheet = spreadsheet.getSheetByName('DatabaseTest');
  const lastRowColumnValuesCash = databaseSheet.getRange("G:G").getValues()
  const lastRowIndexCash = lastRowColumnValuesCash.length - lastRowColumnValuesCash.reverse()
    .findIndex(row => row[0] !== '');
  const importerTicker = importerSheet.getRange("B3").getValue();
  const tickers = databaseSheet.getRange("C3:C").getValues().flat().filter(String);
  const index = tickers.indexOf(importerTicker);
  const rowIndex = index !== -1 ? index * 5 + 3 : lastRowIndexCash + 1;
  console.log(rowIndex)
  if (databaseSheet.getLastRow() + 15 > databaseSheet.getMaxRows()) {
    databaseSheet.insertRowsAfter(databaseSheet.getMaxRows(),databaseSheet.getLastRow() + 15 - databaseSheet.getMaxRows());
  };
  importerSheet.getRange('F3:J40').copyTo(
    databaseSheet.getRange(`G${rowIndex}`),
    SpreadsheetApp.CopyPasteType.PASTE_VALUES,
    true
  );
  importerSheet.getRange('S3:W36').copyTo(
    databaseSheet.getRange(`AT${rowIndex}`),
    SpreadsheetApp.CopyPasteType.PASTE_VALUES,
    true
  );
  importerSheet.getRange('AF3:AJ49').copyTo(
    databaseSheet.getRange(`CC${rowIndex}`),
    SpreadsheetApp.CopyPasteType.PASTE_VALUES,
    true 
    );
  importerSheet.getRange('AS3:AW59').copyTo(
    databaseSheet.getRange(`DY${rowIndex}`),
    SpreadsheetApp.CopyPasteType.PASTE_VALUES,
    true
  );
  importerSheet.getRange('BF3:BJ62').copyTo(
    databaseSheet.getRange(`GE${rowIndex}`),
    SpreadsheetApp.CopyPasteType.PASTE_VALUES,
    true
  );
  importerSheet.getRange('BS3:BW36').copyTo(
    databaseSheet.getRange(`IN${rowIndex}`),
    SpreadsheetApp.CopyPasteType.PASTE_VALUES,
    true
  );
};