【问题标题】:Find table intersect with selection查找与选择相交的表
【发布时间】:2017-02-05 09:07:44
【问题描述】:

我正在寻找与 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));
    }
});

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

谢谢, 扎克

【问题讨论】:

    标签: excel office-js


    【解决方案1】:

    有几种方法可以检查当前选择是否与表格相交。这个 sn-p 演示了其中的两个。

    以下两个示例都是使用 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);
    });
    

    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);
    });
    

    常见的errorHandler helper:

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


    现场试用:您可以在新的脚本实验室 (https://aka.ms/getscriptlab) 中单击五次即可现场试用 Excel 1.4+ 方法。只需安装 Script Lab 插件(免费),然后在导航菜单中选择“导入”,并使用以下 GIST URL:https://gist.github.com/Zlatkovsky/3ebdf5587cdc56d23b289fb6a5645030。见more info about importing snippets to Script Lab

    【讨论】:

    • 仅供参考,更新了此答案以包含截至 2018 年 2 月 1 日的最新信息(TS 2.1 不再处于预览状态,1.4 方法现在非常正式,而不是测试版)。
    猜你喜欢
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 2017-11-25
    • 2010-10-17
    相关资源
    最近更新 更多