当前位置: 首页 > news >正文

开发Excel Add-in的心得笔记

Excel Add-in的笔记

  • 一.基础的cshtml部分-打开taskpane
    • 1.如果你想要tab栏的某个button点击的时候出现的内容显示在taskPane上,那么你可以在对应的cshtml模板文件里加:
    • 2.然后在下面resources标签内要加上:(id一定要对上)
    • 3. 然后去到program.cs里面,添加Route,pattern要和上边的对应上
    • 4. 再去到ExcelAddinController.cs文件里面,加上对应的方法,传进去的"CreateTemplate"就相当于pageName,要对应好要展示的是哪个taskPane
    • 5. 因为要显示在task-pane上,所以就要去task-pane组件里面加上,记得一定要写上page-name是“CreateTemplate”,因为这个页面有很多别的页面出现的情况,所以要区分好
  • 二.Excel addin(基础的cshtml部分-打开dialog)
    • 1.在cshtml文件里改一下
    • 2.在对应的addin-function-aus.ts页面把相应的方法对应起来
      • 2.1 actions.associate 方法用于将自定义事件与一个处理函数关联起来
      • 2.2 处理函数
  • 三.父子组件传参详解(getData,commit,close)
  • 四.给excel填充数据001变成了1
  • 五.ribbon动态显示(enabled和disabled)
  • 六.增删改sheet时数据表格的更新

一.基础的cshtml部分-打开taskpane

存放xml的共享目录地址:\shunified\UnifiedShare\Excel Addin\xml
如果你需要一个新的模板,那就要去Views/ExcelAddin文件夹下创建一个模板,同时记住 < Control> 里面的id是不能一样的,否则这个模板就会无效

1.如果你想要tab栏的某个button点击的时候出现的内容显示在taskPane上,那么你可以在对应的cshtml模板文件里加:

<Action xsi:type="ShowTaskpane"><TaskpaneId>Aus.HomeTaskPane</TaskpaneId><SourceLocation resid="Aus.AddinCreateTemplate.Url" />
</Action>

2.然后在下面resources标签内要加上:(id一定要对上)

<bt:Url id="Aus.AddinCreateTemplate.Url"DefaultValue="@ViewBag.AddinUri/AddinCreateTemplate.html" />

3. 然后去到program.cs里面,添加Route,pattern要和上边的对应上

app.MapControllerRoute(name: "ExcelAddin/AddinCreateTemplate",pattern: "ExcelAddin/AddinCreateTemplate.html",defaults: new { controller = "ExcelAddin", action = "AddinCreateTemplate" }
);

4. 再去到ExcelAddinController.cs文件里面,加上对应的方法,传进去的"CreateTemplate"就相当于pageName,要对应好要展示的是哪个taskPane

public ActionResult AddinCreateTemplate()
{return AddinAUSTaskPane("CreateTemplate");
}

5. 因为要显示在task-pane上,所以就要去task-pane组件里面加上,记得一定要写上page-name是“CreateTemplate”,因为这个页面有很多别的页面出现的情况,所以要区分好

	<create-template if.bind="pageName =='CreateTemplate'" page-name.bind="pageName" is-task-pane="true"></create-template>

二.Excel addin(基础的cshtml部分-打开dialog)

在xml里定义函数名,让他打开指定的dialog(涉及传递数据)

1.在cshtml文件里改一下

<Action xsi:type="ExecuteFunction"><FunctionName>validateSheets</FunctionName></Action>

2.在对应的addin-function-aus.ts页面把相应的方法对应起来

2.1 actions.associate 方法用于将自定义事件与一个处理函数关联起来

actions.associate(CustomEventName.ValidateSheets, this.validateSheets.bind(this));

2.2 处理函数

注意事项:

  • .给要打开的页面指定好pageName:IpageType.WarningAndError

  • 加自己的组件 warning-error-message

  • 去到dialog-page.html页面把自己的组件加上去
    <warning-error-message if.bind="pageName =='WarningAndError'" page-name.bind="pageName" is-task-pane="false"></warning-error-message>

  • 这样dialog里面显示的内容就是我们组件写的内容了

	Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html');
  • 如果要在函数里面传递数据到组件里面,我们可以使用excel addin里面的API

传递思路:
子页面加载好之后,传递信息----->父页面
父页面接收到消息之后,传递信息---->子页面
子页面接收到信息,使用数据
dialog.messageChild(data) 把主页面信息传递到表格里
DialogParentMessageReceived,可以在receivedMessage 里面得到传递过来的数据
messageParent() 把信息从dialog传递到主页面
dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage); 主页面接收dialog传递来的信息

Office.context.ui.addHandlerAsync(Office.EventType.DialogParentMessageReceived, this.receivedMessage.bind(this))
	private validateSheets(event: Office.AddinCommands.Event) {this.writeToDoc("Ribbon button 'Validate' Clicked");let noErrorAndMessage = false;if (noErrorAndMessage) {this.showMessageInDialog("dialogPage.noErrorAndMessageGuide")} else {let allLogs = [{ "errorType": "warning", "message": "lallala" },{ "errorType": "warning", "message": "xoxoxox" }];const startAdress = this.getUrl("AddinDialog") + "?pageName=" + IpageType.WarningAndError;const dialogOptions: Office.DialogOptions = {width: 50,height: 50,displayInIframe: Office.context.platform == Office.PlatformType.OfficeOnline,asyncContext: allLogs};Office.context.ui.displayDialogAsync(startAdress, dialogOptions, (r: Office.AsyncResult<Office.Dialog>) => {// Send allLogs to the dialog when it's loadedlet allLogs = [{ "errorType": "warning", "message": "lallala" },{ "errorType": "warning", "message": "xoxoxox" }];let dialogMessage = {type: DialogMessageType.ValidateSheets,body: {allLogs: allLogs,}};if (r.status == Office.AsyncResultStatus.Failed) {this.writeToDoc(r.error.message);}if (r.status === Office.AsyncResultStatus.Succeeded) {let dialog = r.value;dialog.addEventHandler(Office.EventType.DialogMessageReceived, msg => {this.writeToDoc(JSON.stringify(msg));dialog.messageChild(JSON.stringify(dialogMessage));this.writeToDoc(JSON.stringify(dialogMessage));})}});}event.completed();}

三.父子组件传参详解(getData,commit,close)

父组件向子组件传递数据: 传递思路: 子页面加载好之后,传递信息----->父页面 父页面接收到消息之后,传递信息---->子页面
子页面接收到信息,使用数据

具体详情:我要在点击validate的时候,把读出来的一些warning/error展示在一个dialog里面,我需要把result传到dialog,

createReceivedMessageHandler方法里写的就是具体接收信息做的事情,但是他只是一个中间商,我需要把eventData传递过去,就必须这么写
receivedMessage其实是真正处理接收信息的函数方法

 if (r.status === Office.AsyncResultStatus.Succeeded) {this.dialog = r.value;this.dialog.addEventHandler(Office.EventType.DialogMessageReceived, this.createReceivedMessageHandler(true, eventData));this.highlightCells(this.auditResult);}
private createReceivedMessageHandler(showCommitButtonValue,eventData) {return (args) => {this.receivedMessage(this.dialog, args, showCommitButtonValue,eventData);};
}

auditResult就是要传递给子组件的数据,需要先得到子组件发给父组件的信息我们再传过去
commit是子组件传过来的(证明用户点击了commit button),然后我们直接调用更新的graphql语句

private async receivedMessage(dialog: Office.Dialog, args: { message: string }, showCommitButton?: boolean,eventData?) {let dialogMsg: IDialogMessage = JSON.parse(args.message);this.writeToDoc("receivedMessage from child: " + args.message);if (dialogMsg.type == DialogMessageType.RequestValidateSheetsInfo) {let dialogMessage = {type: DialogMessageType.ValidateSheets,body: {auditResult: this.auditResult,showCommitButton: showCommitButton,eventData: eventData}};dialog.messageChild(JSON.stringify(dialogMessage));} else if (dialogMsg.type == DialogMessageType.Commit) {await this.schedulingAgent.addAndUpdateReceiptEvents(eventData);dialog.close();this.writeToDoc("commit successfully");} else if (dialogMsg.type == DialogMessageType.Close) {dialog.close();} else if (dialogMsg.type == DialogMessageType.CreateEnd) {dialog.close();this.writeToDoc("add case successfully");}}

四.给excel填充数据001变成了1

使用 numberFormat 属性将单元格格式设置为文本。‘@’ 是 Excel 中表示文本格式的符号。
在这里插入图片描述

五.ribbon动态显示(enabled和disabled)

需要根据逻辑判断来决定是否enabled或者disabled,一定要把id对应好

发送信息:

parent.postMessage({ action: "updateRibbonState", selectedData: workspace.connected }, "*");

接收信息并更新ribbon:

window.addEventListener("message", (event) => {if (event.data.action == "updateRibbonState") {let buttonEnabled = event.data && event.data.selectedData;updateRibbonButtons(buttonEnabled);}
});

一定要注意,如果有共享的内容需要在taskpane显示,这个taskpane的id一定要是唯一的!!!不能和别的共享,否则会出现不能正常加载的问题
• Office 客户端会根据 TaskpaneId 判断是否已存在同 ID 的任务窗格。若存在,则会尝试复用(如刷新内容),而非重复创建新实例
例如:若两个按钮共享同一个 TaskpaneId,点击第二个按钮时会直接激活已存在的窗格,而非打开新页面。

六.增删改sheet时数据表格的更新

  1. 事件监听器注册:
    • 在 attached 方法中调用 registerWorksheetAddedListener 方法注册工作表添加事件监听器。
    • 使用 this.handleWorksheetAdded.bind(this) 确保事件处理函数中的 this 指向正确的上下文。
  2. 事件处理函数:
    • 在 handleWorksheetAdded 方法中,使用 await context.sync() 确保在获取工作表名称后,再更新 mappingData。
    • 更新 mappingData 后,调用 saveToCache 方法保存数据。
    • 调用 this.gridOptions.api.setRowData(this.mappingData) 更新网格数据。
  3. 确保网格更新:
    • 在事件处理函数中,确保 this.gridOptions.api 存在,再调用 setRowData 方法
private registerWorksheetAddedListener() {Excel.run(async (context) => {const worksheetCollection = context.workbook.worksheets;worksheetCollection.onAdded.add(this.handleWorksheetAdded.bind(this));await context.sync();console.log("Event handler successfully registered for onAdded event in the worksheet collection.");});}private async handleWorksheetAdded(event: Excel.WorksheetAddedEventArgs) {await Excel.run(async (context) => {const worksheet = context.workbook.worksheets.getItem(event.worksheetId);worksheet.load("name");await context.sync();this.mappingData.push({sheetName: worksheet.name,templateName: "",active: false,});this.saveToCache(this.mappingData);if (this.gridOptions && this.gridOptions.api) {this.gridOptions.api.setRowData(this.mappingData);this.onGridResize();}console.log("A new worksheet has been added: " + worksheet.name);});}
http://www.xdnf.cn/news/1292329.html

相关文章:

  • [系统架构]系统架构基础知识(一)
  • 基于elk实现分布式日志
  • 2025 开源语音合成模型全景解析:从工业级性能到创新架构的技术图谱
  • 我们计划编写一个闲鱼监控脚本,主要功能是监控特定关键词的商品,并在发现新商品时通过钉钉机器人推送通知。
  • LCP 17. 速算机器人
  • 从开发工程师视角看TTS语音合成芯片
  • 基于数据驱动来写提示词(一)
  • 机器学习项目从零到一:加州房价预测模型(PART 3)
  • 【论文笔记】DOC: Improving Long Story Coherence With Detailed Outline Control
  • Excel多级数据结构导入导出工具
  • 2025 环法战车科技对决!维乐 Angel Glide定义舒适新标
  • [AI React Web] E2B沙箱 | WebGPU | 组件树 | 智能重构 | 架构异味检测
  • 面试实战 问题二十九 Java 值传递与引用传递的区别详解
  • 汽车免拆诊断案例 | 2017 款丰田皇冠车行驶中加速时车身偶尔抖动
  • 【国内电子数据取证厂商龙信科技】RAID存储技术
  • 浅谈TLS 混合密钥交换:后量子迁移过渡方案
  • 汽车高位制动灯难达 CIE 标准?OAS 光学软件高效优化破局
  • 【分布式 ID】一文详解美团 Leaf
  • 服务器通过生成公钥和私钥安全登录
  • Spring cloud集成ElastictJob分布式定时任务完整攻略(含snakeyaml报错处理方法)
  • 华为悦盒EC6108V9-1+4G版-盒子有【蓝色USB接口】的特殊刷机说明
  • 机器翻译:学习率调度详解
  • 2025 电赛 C 题完整通关攻略:从单目标定到 2 cm 测距精度的全流程实战
  • 图论理论部分
  • 云计算-OpenStack 实战运维:从组件配置到故障排查(含 RAID、模板、存储管理,网络、存储、镜像、容器等)
  • Python3解释器深度解析与实战教程:从源码到性能优化的全路径探索
  • amis表单较验
  • 数据结构:用数组实现队列(Implementing Queue Using Array)
  • Go 语言函数详解:从基础到高阶的行为逻辑构建
  • 洛谷 小 Y 拼木棒 贪心