Office Javascript API。将行移动到另一张纸时出现问题

问题描述 投票:0回答:1

我创建了一个小函数,使用 Office javascript api 将一行移动到另一个工作表,但遇到了一个小问题。我用删除线文本标识所有行,然后将它们移动到存档表中。问题似乎出在线路上

dataRange.getRow(row).moveTo(targetSheet.getRange("A" + tglastrowindex));  

如果此行被注释掉,则变量 tglastrowindex 在 for 循环的每次迭代中都会正确递增,但如果启用该行,则该行会正确移动,但 tglastrowindex 变量不会递增,因此它会覆盖该行,而不是在该行的最后一行之后添加存档表。

不太确定是什么原因造成的,但可能与行移动有关?有人以前遇到过这个问题或者可以帮忙解决吗?

async function archive() {
    await Excel.run(async (context) => {
      worksheet = context.workbook.worksheets.getActiveWorksheet();
      await context.sync();
      console.log("archiving");
      let myUsedRange = worksheet.getUsedRange();
      let lastrow = myUsedRange.getLastRow().load(["rowindex", "values"]);
      await context.sync();
      let lastrowindex = lastrow.rowIndex + 1;

      //console.log(JSON.stringify(lastrow.rowIndex + 1, null, 4));

      let dataRange = worksheet.getRange("A5:M" + lastrowindex).load(["rowCount", "rowIndex"]);
      await context.sync();
      
      var tglastrowindex = 0;
      var targetSheet;
      var tgUsedRange;
      var tglastrow;
      var cnt = 0;

      for (var row = 0; row < dataRange.rowCount; row++) {
        //dataRange.getRow(row).format.fill.clear();
        //console.log("tglastrowindex1:" + tglastrowindex);
        let dataCell = dataRange.getCell(row, 1).load(["format/font/strikethrough"]);
        await context.sync();

        //console.log(JSON.stringify(dataCell, null, 4));
          
        if (dataCell.format.font.strikethrough == true) {
          //console.log("strikethrough detected");
          worksheet.load("name");
          await context.sync();
          //console.log("sourcesheetname:" + worksheet.name);
          if (worksheet.name == "Sheet1") {
            //console.log("worksheet detected");
            targetSheet = context.workbook.worksheets.getItem("Archive").load("name");
            await context.sync();
            //console.log("targetsheet name:" + targetSheet.name);        
            tgUsedRange = targetSheet.getUsedRange();                      
            tglastrow = tgUsedRange.getLastRow().load(["rowindex", "values"]);
            await context.sync();             
            if(cnt == 0){
              tglastrowindex = tglastrow.rowIndex + 1;
              cnt = cnt + 1;
            }
            else {
              tglastrowindex = tglastrowindex + 1;
            }                                            
            console.log("targetsheet index:" + tglastrowindex);
                      
            
            dataRange.getRow(row).moveTo(targetSheet.getRange("A" + tglastrowindex));   
            
          }                 
                          
        }            
      }
      
    });
  
javascript excel office-js exceljs
1个回答
0
投票

首先,我会投票赞成问题,但它不包括最小的、可重现的示例。一个好的问题应该包含一个“创建数据”代码示例,这样我们就可以创建数据,然后创建问题。

参见 --> https://stackoverflow.com/help/minimal-reproducible-example

我在问题中创建示例数据的另一个示例 --> 自定义排序列 - Excel Javascript - Office-JS

同样,关于您的代码,我看到很多

context.sync
,这是应该避免的,特别是在循环内部。不幸的是,无法加载范围内的单个单元格格式属性,因此您必须对每个单元格进行批量同步调用。我没有测试这段代码,比如 >50K 行,但是如果您的工作簿太大并且需要批量同步并循环下面构建
st_rows_arr_of_ri
数组的整个代码,您将会遇到问题。

参见 --> 使用 Office.js 在 Excel 中获取单个单元格格式?

关于您的问题,对我来说突出的一个问题是您对

A1
范围格式约定的使用。尝试仅在使用范围时使用数字,例如
getRangeByIndexes
。在开始写入之前,您只需要找到
Archive
工作表的最后一行一次,然后您就可以跟踪内存中的
lastrow
并递增,而无需检查/同步每个循环/写入。

这是我最终得到的一些示例代码,这就是我如何从整体上解决上述问题。非常通用,我没有从现有工作表中删除这些行,如果是这样,您可能会想要反向执行此操作,并且我为下面的某些代码提供了外部函数,但我在本示例中将其全部构建在一个函数中。

var ws = context.workbook.worksheets.getActiveWorksheet();

//Create fake data
ws.getRange("A1:C10").values = "TEST" 
ws.getRange("A2:C2").format.font.strikethrough = true
ws.getRange("A10:C10").format.font.strikethrough = true
await context.sync()

//Get UsedRng rowCount/Index
var Used_Rng_And_Props = ws.getUsedRange(true);
var load_opts_arr = [
    "rowCount",
    "rowIndex",
];
Used_Rng_And_Props.load(load_opts_arr)
await context.sync();

//Sync up cell formats array
var cell_formats_arr = []
//https://stackoverflow.com/questions/35647790/get-individual-cell-formats-in-excel-using-office-js
var load_opts_arr = [
    "format/font/strikethrough",
    "rowIndex",
]
for (let ri = Used_Rng_And_Props.rowIndex; ri < Used_Rng_And_Props.rowCount; ri++) {
    cell_formats_arr.push(ws.getRangeByIndexes(ri, 0, 1, 1).load(load_opts_arr))
}
await context.sync()

//Get all row indexes w/ cells in Column 0 with strikethrough text
var st_rows_arr_of_ri = []
for (let ai = 0; ai < cell_formats_arr.length; ai++) {
    var cell = cell_formats_arr[ai]
    if (cell.format.font.strikethrough == true) {
        st_rows_arr_of_ri.push(cell.rowIndex)
    }
}
var cell_formats_arr = null

//Get Dest Sheet and add Fake Data
var targetSheet = context.workbook.worksheets.add("archive")
targetSheet.getRange("A1:A3").values = "FakeExistingData"
await context.sync()

//Get Dest Sheet Last Row
var targetSheet_Used_Rng_And_Props = targetSheet.getUsedRange(true)
var load_opts_arr = [
    "rowCount",
    "rowIndex",
];
targetSheet_Used_Rng_And_Props.load(load_opts_arr)
await context.sync()
var row_ct = targetSheet_Used_Rng_And_Props.rowIndex + targetSheet_Used_Rng_And_Props.rowCount

//Move Data
for (let ai = 0; ai < st_rows_arr_of_ri.length; ai++) {
    var ri = st_rows_arr_of_ri[ai]
    console.log('ri: ' + ri)
    var src_rng = ws.getUsedRange(true).getRow(ri)
    var dst_rng = targetSheet.getRangeByIndexes(row_ct, 0, 1, 1) //Use getRangeByIndexes to remove need for row 0 check for A1 rng format
    src_rng.moveTo(dst_rng);
    row_ct = row_ct + 1
}
await context.sync()
© www.soinside.com 2019 - 2024. All rights reserved.