You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Office Scripts过滤问题:如何获取表格可见行的第一列数据

Office Scripts筛选后获取可见行第一列数据问题修复

问题描述

我正在编写一个Office Scripts脚本,目标是筛选数据并找到第一列包含AB S.A.、Ingram Micro spółka z o.o.、ALSO Polska Sp. z o.o.这三个字符串的最新日期,计划通过逐个日期应用过滤并检查的方式实现。目前代码其余部分运行正常,但最后一段获取可见行第一列数据的逻辑有问题:打印firstColumnValues时显示的是整个表格的所有行数据,而非仅当前可见行。

原代码如下:

function main(workbook: ExcelScript.Workbook) {
let selectedSheet = workbook.getActiveWorksheet();
const INV = workbook.getWorksheet("INV");


// Adding function formatDate which is converting date to format: DD/MM/YYYY
function formatDate(date: Date) {
    var year: string = date.getFullYear().toString();
    var month: string = (date.getMonth() + 101).toString().substring(1);
    var day: string = (date.getDate() + 100).toString().substring(1);
    return day + "/" + month + "/" + year;
}


// Deleting unnecessary columns
// Delete range A:C on selectedSheet
selectedSheet.getRange("A:C").delete(ExcelScript.DeleteShiftDirection.left);
// Delete range B:C on selectedSheet
selectedSheet.getRange("B:C").delete(ExcelScript.DeleteShiftDirection.left);
// Delete range D:E on selectedSheet
selectedSheet.getRange("D:E").delete(ExcelScript.DeleteShiftDirection.left);
// Delete range E:H on selectedSheet
selectedSheet.getRange("E:H").delete(ExcelScript.DeleteShiftDirection.left);

// Create a new temporary sheet view
selectedSheet.enterTemporaryNamedSheetView();
// Clear auto filter on selectedSheet
selectedSheet.getAutoFilter().clearCriteria();
// Toggle auto filter on selectedSheet
selectedSheet.getAutoFilter().remove();


// 
const usedRange = INV.getUsedRange();
const lastRowRange = usedRange.getLastRow();
const lastRow = lastRowRange.getRowIndex();
const tableRange = INV.getRange("A1:C" + lastRow.toString());
let newTable = INV.addTable(tableRange, true);



// Creating an array, that contains current date and last 6 days

let daysArray: Date[] = [];
let now = new Date();
for (let i = 0; i < 6; i++) {
    daysArray.push(new Date(now.setDate(now.getDate() - 1)));
}
daysArray.unshift(new Date());

let formattedDaysArray = daysArray.map((date) => formatDate(date));


// Create an array that contains unique values from "Calendar day" column
const keyDateColumnValues: string[] = newTable.getColumnByName("Calendar                 day").getRangeBetweenHeaderAndTotal().getValues().map(v => v[0] as string);
const uniqueDates = keyDateColumnValues.filter((v, i, a) => a.indexOf(v) === i);

// Create an array that contains unique values from "Distributor Name" column
const keyColumnValues: string[] = newTable.getColumnByName("Calendar day").getRangeBetweenHeaderAndTotal().getValues().map(v => v[0] as string);
const uniqueDist = keyColumnValues.filter((v, i, a) => a.indexOf(v) === i);


// Convering array of strngs: uniqueDates to array of dates
let dates: Date[] = [];
for (let i = 0; i < uniqueDates.length; i++) {
  //let nowaData = new Date(uniqueDates[i]);

var dateParts = uniqueDates[i].split("/");

// month is 0-based, that's why we need dataParts[1] - 1
var nowaData = new Date(+parseInt(dateParts[2]), parseInt(dateParts[1]) - 1, +parseInt(dateParts[0])); 

  dates.push(nowaData);
}

// Sorting an array 
dates.sort((a, b) => a.getTime() - b.getTime());

// Convering to date format: dd/mm/yyyy
let formattedDatesArray = dates.map((date) => formatDate(date));
console.log(formattedDatesArray);

console.log(formattedDatesArray[0]);

// Apply custom filter on table tabela1 column "Distributor Name"
newTable.getColumnByName("Distributor Name").getFilter().applyCustomFilter("=Exclusive*");

// Remove filtered range
let visibleRows = newTable.getRangeBetweenHeaderAndTotal().getVisibleView().getRows();
let firstVisibleRow = visibleRows[0].getRange().getRowIndex() + 1;
let lastVisibleRow = visibleRows[visibleRows.length - 1].getRange().getRowIndex() + 1;

                INV.getRange(`${firstVisibleRow}:${lastVisibleRow}`).delete(ExcelScript.DeleteShiftDirection.up);

newTable.getColumnByName("Distributor Name").getFilter().clear();

newTable.getColumnByName("Calendar day").getFilter().applyValuesFilter([formattedDatesArray[0]]);



let visibleRows2 = newTable.getRangeBetweenHeaderAndTotal().getVisibleView().getRows();
let firstVisibleRow2 = visibleRows2[0].getRange().getRowIndex() + 1;
let lastVisibleRow2 = visibleRows2[visibleRows2.length - 1].getRange().getRowIndex() + 1;

let firstColumn = INV.getRange('A'+ firstVisibleRow2 + ':'+ 'A' + lastVisibleRow2);
let firstColumnValues = firstColumn.getValues();
//console.log(firstColumnValues);

const containsXYZ = firstColumnValues.some(str => str.includes('AB S.A.')&&('Ingram Micro spółka  z o.o.')&&('ALSO Polska Sp. z o.o.'));
console.log(containsXYZ);
}

解决方案

问题根源在于直接使用工作表的getRange方法获取范围时,该方法会忽略过滤状态,返回指定行号的完整范围,不管行是否被隐藏。正确的做法是从可见行集合visibleRows2中逐个提取第一列的单元格值。

同时,原代码中检查经销商的逻辑存在错误:使用&&会要求单个单元格同时包含三个经销商名称,这显然不符合需求,应该用||判断单元格是否包含任意一个目标经销商。

修改后的代码片段

替换原代码中最后一段获取firstColumnValues和判断的逻辑:

let visibleRows2 = newTable.getRangeBetweenHeaderAndTotal().getVisibleView().getRows();

// 收集可见行的第一列数据
let firstColumnValues: string[] = [];
for (let row of visibleRows2) {
  // 获取当前可见行的第一列(A列,索引为0)单元格值
  const cellValue = row.getRange().getColumn(0).getValue() as string;
  firstColumnValues.push(cellValue);
}

// 检查是否存在任意一个目标经销商
const containsTargetDistributors = firstColumnValues.some(str => 
  str.includes('AB S.A.') || str.includes('Ingram Micro spółka z o.o.') || str.includes('ALSO Polska Sp. z o.o.')
);
console.log(containsTargetDistributors);

说明

  • 通过遍历visibleRows2(过滤后的可见行集合),每一行调用getColumn(0)获取第一列,再通过getValue()提取单元格内容,确保只获取可见行的数据。
  • 将&&替换为||,实现"只要存在任意一个目标经销商即返回true"的逻辑,符合你的需求。

内容的提问来源于stack exchange,提问作者Shaienne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 05:12:19