[TOC] > Sat May 01 2021 20:55:51 GMT+0800 (GMT+08:00) 为工作表创建目录(实质是跳转到指定工作表的超链接),我们用宏的方式批量创建,并利用工作表新增、删除、重命名事件自动更新目录。 > 跨工作簿的链接无法更新,因为工作表事件仅针对当前工作簿(除非双向部署) 其实吧,目录就是由超链接构成的,当工作表变多的时候定位比较困难,有个目录就很方便了。 这里先提供低级版的(占用单元格) > 可能会出加载项版的,窗体版的因 WPS JSAPI 缺少 UserForm 的说明,还不知道如何进行。 ## 低配版目录 > 会占用单元格。后续的章节提供“中配版”——窗体目录。 为 WPS 表格 工作表插入目录 注意,**目录所在列不应再填入数据(它们会随工作表数量变化而变化),有被覆盖、清除的可能性。** 使用方法: * 复制当前代码到 WPS JS宏编辑器的模块内。 * 新建你自己的宏,然后通过 new 使用。 * 要想变成"智能"目录,请将宏加入到Application、Workbook级别的事件内部。 > "智能":随工作簿工作表的增、删、隐藏(取消隐藏)而更新目录。 **Kind**: global class * [shSummary](#shSummary) * [new shSummary(anchor, options)](#new_shSummary_new) * [.selectRange](#shSummary+selectRange) * [.addToFirRange](#shSummary+addToFirRange) * [.sHname](#shSummary+sHname) * [.sH](#shSummary+sH) * [.wb](#shSummary+wb) * [._getWbNames()](#shSummary+_getWbNames) * [._getSheetNames(wbName, ignoreHiddenOne)](#shSummary+_getSheetNames) * [._clearRanges()](#shSummary+_clearRanges) * [.thisWorkbookSummary()](#shSummary+thisWorkbookSummary) * [.otherWorkbookSummary()](#shSummary+otherWorkbookSummary) * [.addSummary()](#shSummary+addSummary) <a name="new_shSummary_new"></a> ### new shSummary(anchor, options) | Param | Type | Description | | --- | --- | --- | | anchor | <code>string</code> | 目录插入点,例如:'Sheet1!A1' | | options | <code>object</code> | | | options.selectRange | <code>string</code> | 跳转到的具体单元格名,例如:'A3',即跳转后被选中的单元格,默认每个工作表的 A1 单元格。 | | options.useNameAsLinkText | <code>boolean</code> | 仅使用工作表名称作为链接文本(false则带`selectRange`的值,true则只显示表名),其他工作簿的链接始终带有工作簿名(如果`forAllOpenedWorkbook`为 true的话)。 | | options.ignoreHiddenSheets | <code>boolean</code> | 是否忽略隐藏工作表,默认 true:忽略(因为隐藏的工作表是无法显示的,结果是“死链”点击时会提示引用无效) | | options.forAllOpenedWorkbook | <code>boolean</code> | 是否将所有的打开的工作簿都纳入目录(注意:本工作簿以外的工作簿的工作表事件无法监测,但会在生成更新本工作簿目录时跑一遍其他工作簿),默认 false;不加入目录。 | **Example** ```js function _m_addSummary(){ let summary = new shSummary("Sheet1!A1",{selectRange="A1"}) // 具体配置可以自行查看文档(都有默认值,可不配置,仅提供目录插入点即可) summary.addSummary() // 创建目录 } ``` <a name="shSummary+selectRange"></a> ### shSummary.selectRange 链接目标单元格 **Kind**: instance property of [<code>shSummary</code>](#shSummary) <a name="shSummary+addToFirRange"></a> ### shSummary.addToFirRange 插入目录区域的第一格 **Kind**: instance property of [<code>shSummary</code>](#shSummary) <a name="shSummary+sHname"></a> ### shSummary.sHname 工作表名 **Kind**: instance property of [<code>shSummary</code>](#shSummary) <a name="shSummary+sH"></a> ### shSummary.sH 目录所在工作表 **Kind**: instance property of [<code>shSummary</code>](#shSummary) <a name="shSummary+wb"></a> ### shSummary.wb 目录所在工作簿 **Kind**: instance property of [<code>shSummary</code>](#shSummary) <a name="shSummary+_getWbNames"></a> ### shSummary.\_getWbNames() 获取当前打开的所有工作簿名称(新建未保存工作簿将忽略) **Kind**: instance method of [<code>shSummary</code>](#shSummary) <a name="shSummary+_getSheetNames"></a> ### shSummary.\_getSheetNames(wbName, ignoreHiddenOne) 获取某一工作簿所有工作表名称。 **Kind**: instance method of [<code>shSummary</code>](#shSummary) | Param | Type | Description | | --- | --- | --- | | wbName | <code>string</code> | 工作簿名称 | | ignoreHiddenOne | <code>boolean</code> | 是否忽略隐藏工作表 | <a name="shSummary+_clearRanges"></a> ### shSummary.\_clearRanges() 清除目录 **Kind**: instance method of [<code>shSummary</code>](#shSummary) <a name="shSummary+thisWorkbookSummary"></a> ### shSummary.thisWorkbookSummary() 创建本(宏所在的)工作簿的目录 **Kind**: instance method of [<code>shSummary</code>](#shSummary) <a name="shSummary+otherWorkbookSummary"></a> ### shSummary.otherWorkbookSummary() 将其他工作簿纳入目录 **Kind**: instance method of [<code>shSummary</code>](#shSummary) <a name="shSummary+addSummary"></a> ### shSummary.addSummary() 创建目录 **Kind**: instance method of [<code>shSummary</code>](#shSummary) ## 代码 ```js /** * 为 WPS 表格 工作表插入目录 * * 注意,**目录所在列不应再填入数据(它们会随工作表数量变化而变化),有被覆盖、清除的可能性。** * * * 使用方法: * * * 复制当前代码到 WPS JS宏编辑器的模块内。 * * 新建你自己的宏,然后通过 new 使用。 * * 要想变成"智能"目录,请将宏加入到Application、Workbook级别的事件内部。 * * > "智能":随工作簿工作表的增、删、隐藏(取消隐藏)而更新目录。 * * @example * * function _m_addSummary(){ * let summary = new shSummary("Sheet1!A1",{selectRange="A1"}) // 具体配置可以自行查看文档(都有默认值,可不配置,仅提供目录插入点即可) * summary.addSummary() // 创建目录 * } * * @class */ class shSummary { /** * * @param {string} anchor 目录插入点,例如:'Sheet1!A1' * @param {object} options * @param {string} options.selectRange 跳转到的具体单元格名,例如:'A3',即跳转后被选中的单元格,默认每个工作表的 A1 单元格。 * @param {boolean} options.useNameAsLinkText 仅使用工作表名称作为链接文本(false则带`selectRange`的值,true则只显示表名),其他工作簿的链接始终带有工作簿名(如果`forAllOpenedWorkbook`为 true的话)。 * @param {boolean} options.ignoreHiddenSheets 是否忽略隐藏工作表,默认 true:忽略(因为隐藏的工作表是无法显示的,结果是“死链”点击时会提示引用无效) * @param {boolean} options.forAllOpenedWorkbook 是否将所有的打开的工作簿都纳入目录(注意:本工作簿以外的工作簿的工作表事件无法监测,但会在生成更新本工作簿目录时跑一遍其他工作簿),默认 false;不加入目录。 */ constructor(anchor, options = { selectRange: "A1", useNameAsLinkText: true, ignoreHiddenSheets: true, forAllOpenedWorkbook: false }) { let a, b, c; if (options.useNameAsLinkText == undefined || options.useNameAsLinkText == null) { a = true } else { a = options.useNameAsLinkText } if (options.ignoreHiddenSheets == undefined || options.ignoreHiddenSheets == null) { b = true } else { b = options.ignoreHiddenSheets } if (options.forAllOpenedWorkbook == undefined || options.forAllOpenedWorkbook == null) { c = false } else { c = options.forAllOpenedWorkbook } /** 链接目标单元格*/ this.selectRange = options.selectRange || "A1"; // 默认为 A1 /** 插入目录区域的第一格*/ this.addToFirRange = Range(anchor) /** 工作表名*/ this.sHname = this.addToFirRange.Parent.Name; /** 目录所在工作表*/ this.sH = Worksheets.Item(this.sHname) this.wbName = this.sH.Parent.Name; /** 目录所在工作簿*/ this.wb = Workbooks.Item(this.wbName) this.useNameAsLinkText = a; this.ignoreHiddenSheets = b; this.forAllOpenedWorkbook = c; /* this.useNameAsLinkText = options.useNameAsLinkText ?? true; this.ignoreHiddenSheets = options.ignoreHiddenSheets ?? true; this.forAllOpenedWorkbook = options.forAllOpenedWorkbook ?? false; */ } /** 获取当前打开的所有工作簿名称(新建未保存工作簿将忽略)*/ _getWbNames() { let n = []; for (let i = 1; i <= Application.Workbooks.Count; i++) { let item = Workbooks.Item(i).Name if (item !== "") { n.push(Workbooks.Item(i).Name) } } return n; } /** * 获取某一工作簿所有工作表名称。 * @param {string} wbName 工作簿名称 * @param {boolean} ignoreHiddenOne 是否忽略隐藏工作表 */ _getSheetNames(wbName, ignoreHiddenOne) { let wb = wbName || this.wbName let curWb = Workbooks.Item(wb) let n = [] for (let i = 1; i <= curWb.Worksheets.Count; i++) { let item = curWb.Worksheets.Item(i) let ishidden = item.Visible let iname = item.Name if (ishidden && !ignoreHiddenOne) { n.push([wbName, iname]) } if (ishidden) { n.push([wbName, iname]) } } return n; } /** * 清除目录 */ _clearRanges() { let summRang = this.addToFirRange; let nextRisBlank = summRang.Offset(1, 0).Value() == null; if (!nextRisBlank) { Range(summRang, summRang.End(xlDown)).Value2 = undefined; } } /** * 创建本(宏所在的)工作簿的目录 */ thisWorkbookSummary() { let TR = this.selectRange let SR = this.addToFirRange let igHidden = this.ignoreHiddenSheets let useName = this.useNameAsLinkText this._clearRanges() // 开始写入 let links = this._getSheetNames(this.wbName, igHidden) if (links.length == 0) { return } for (let i = 0; i < links.length; i++) { let link_text; let item = links[i][1] if (useName) { link_text = item } else { link_text = `${item}!${TR}` } let fo = { link: `${item}!${TR}`, text: link_text } let summitem = SR.Offset(i, 0) let tSh = this.sH tSh.Hyperlinks.Add(summitem, "", fo.link, "", fo.text) } } /** * 将其他工作簿纳入目录 */ otherWorkbookSummary() { if (this.forAllOpenedWorkbook == false) { return } let allWb = this._getWbNames() let fo = allWb.indexOf(this.sHname) allWb.splice(fo, 1)// 剔除当前工作簿 let allWb_sheets = [] for (let i = 1; i <= a.length; i++) { let item = a[i] let item_SheetNames = this._getSheetNames(item, this.ignoreHiddenSheets) allWb_sheets.push(item_SheetNames) } // 查找目录末尾单元格 let lastRange = this.addToFirRange.End(xlDown) for (let p = 0; p < allWb_sheets.length; p++) { let ptem = allWb_sheets[i] // [wbname,shname] let summaryLi_text if (this.useNameAsLinkText) { summaryLi_text = ptem.join('!') } else { summaryLi_text = `${ptem.join('!')}${this.selectRange}` } let summaryLi = { text: summaryLi_text, link: `[${ptem[0]}]${ptem[1]}!${this.selectRange}` } let nextSummaryAddTo = lastRange.Item(i, 0) let summarySh = this.sH; summarySh.Hyperlinks.Add(nextSummaryAddTo, "", summaryLi.link, "", summaryLi.text) } } /** * 创建目录 */ addSummary() { // 先添加本工作表 this.thisWorkbookSummary() // 接着补其他工作簿 this.otherWorkbookSummary() } } ```