查找表与选择相交

Zac*_*sse 3 excel office-js

我正在寻找与 Excel VBA Intersect 方法等效的 Javascript。我需要找到活动单元格表。基本上,我对表格所做的一切都基于用户当前选择的表格。IIRC,目前没有办法直接做到这一点。所以我想要做的基本上是这样的:

  • 获取选定的范围(仍然不完美,因为我真的只想要ActiveCell,而不是Selection)。
  • 获取工作表。
  • 循环遍历工作表上的所有表格。
  • 检查每个表,查看所选范围是否在表范围内。

我有点摸不着头脑,这就是我目前所拥有的,但不起作用......

Excel.run(function(ctx) {

    var Selection = ctx.workbook.getSelectedRange();
    var Tables = ctx.workbook.tables;
    var TableNames = ctx.workbook.tables.load("name");

    for (var i = 0; i < TableNames.items.length; i++)
    {
        var Table = ctx.workbook.tables.getItem(TableNames.items[i].name);
        Table.getRange().load('address');
        var Intersect = Selection.getBoundingRect(Table.getRange().address);
        if (Intersect != null) {return ctx.sync().then(function() {
            TableNames.items[i].name;
        })};
    }

    return ctx.sync();
}).catch(function(error) {
    console.log(error);
    if (error instanceof OfficeExtension.Error) {
        console.log("Debug info: " + JSON.stringify(error.debugInfo));
    }
});
Run Code Online (Sandbox Code Playgroud)

如果它是原生的,这将是 API 向前迈出的重要一步。;)

谢谢,扎克

Mic*_*oft 5

有几种方法可以检查当前选择是否与表格相交。此代码段演示了其中的两个。

下面的两个示例都是使用 TypeScript 2.1+ 的 async/await 语法编写的。第二种方法通过使用“await”变得更加简单,但是这两种方法也可以通过常规的 promise-chaining 来实现。

  1. ExcelApi 1.4+ 的效率要高得多,但它只能在较新版本的 Excel 上运行(基于订阅,而不是 2016 MSI/RTM)。它同时进行所有的交叉检查。
  2. 如果您有数百个表,或者您在 Excel Online 上运行,则 ExcelApi 1.1 版本的效率较低。它需要对服务器进行更多的往返,因为它会一一检查每个表交集,并依靠抛出的错误来通知它没有找到交集。

ExcelApi 1.4+ 方法:

$('#check-intersection-preview').click(function() {
    // Note: this function uses a "Preview" API ("range.getIntersectionOrNull"),
    // which is only available on the Beta CDN right now, and is subject to change.
    // Do not rely on this for production. Instead, use the alternate
    // (albeit less neat) version.

    Excel.run(async function(context) {
        var selection = context.workbook.getSelectedRange();
        var tables = context.workbook.tables.load("name");
        await context.sync();

        var intersections: { [email: string]: Excel.Range } = { };
        tables.items.forEach((table) => {
            intersections[table.name] = table.getRange().
                getIntersectionOrNullObject(selection).load("address");
        });
        await context.sync();

        var found = false;
        for (var tableName in intersections) {
            var rangeOrNull = intersections[tableName];
            if (!rangeOrNull.isNullObject) {
                found = true;
                console.log(`Intersection found with table "${tableName}". ` +
                    `Intersection range: "${rangeOrNull.address}".`);
            }
        }
        if (!found) {
            console.log("Selection does not intersect any table");
        }
    }).catch(errorHandler);
});
Run Code Online (Sandbox Code Playgroud)

ExcelApi 1.1 方法:

$('#check-intersection-prod').click(function() {
    Excel.run(async function(context) {
        var selection = context.workbook.getSelectedRange();
        var tables = context.workbook.tables.load("name");
        await context.sync();

        var found = false;        
        for (var i = 0; i < tables.items.length; i++) {
            try {
                var table = tables.items[i];
                var intersectionRange = table.getRange()
                    .getIntersection(selection).load("address");
                await context.sync();

                // If reached past the sync, it means that "getIntersection"
                // did not throw an error, and so the intersection must be valid.
                found = true;
                console.log(`Intersection found with table "${table.name}". ` +
                    `Intersection range: "${intersectionRange.address}".`);

            } catch (e) {
                var isExpectedError = e instanceof OfficeExtension.Error &&
                    (<OfficeExtension.Error>e).code === Excel.ErrorCodes.itemNotFound;

                if (!isExpectedError) {
                    throw e;
                } 
            }
        }

        if (!found) {
            console.log("Selection does not intersect any table");
        }
    }).catch(errorHandler);
});
Run Code Online (Sandbox Code Playgroud)

常见的 errorHandler 帮助器:

function errorHandler(error) {
    console.log(error);
    if (error instanceof OfficeExtension.Error) {
        console.log("Debug info: " + JSON.stringify(error.debugInfo));
    }
}
Run Code Online (Sandbox Code Playgroud)


现场试用:您可以在新的 Script Lab ( https://aka.ms/getscriptlab ) 中点击五下,现场试用 Excel 1.4+ 方法。只需安装 Script Lab 插件(免费),然后在导航菜单中选择“导入”,并使用以下 GIST URL:https : //gist.github.com/Zlatkovsky/3ebdf5587cdc56d23b289fb6a5645030。查看有关将片段导入 Script Lab 的更多信息