node.js用activex/com+自动化读写excel时查询接口、参数的调试方法


发布者 ourjs  发布时间 1686215017210
关键字 Node.JS  ActiveX|COM+ 

在某个 excel 的自动化应用中,打开某个特殊的文件时,会一直弹出一个对话框,提示:

This workbook contains links to one or more external sources that could be unsafe.
If you trust the links, update them to get the latest data. Otherwise, you can keep working with the data you have.

只有手动关了对话框,自动化程序才能进行下一步,网上也搜索不到现成的解决方案。

我们的程序是使用的 winax 模块,通过COM+接口操作的excel,理论上excel上所有手动操作都应该可以通过程序来控制,比如我们之前添加的忽略警告 displayAlerts = false 的设置

/**
 * If activate is true: cannot run two instance the second time
 */
const $excel = new winax.Object("Excel.Application", { activate: false });
$excel.displayAlerts = false
$excel.visible = true

所以应该有一个接口可以阻止弹出这个contains unsafe links,对话框。下面介绍一下如何在JS里通过LOG来找到这个接口。

在JS里找到对象的接口还是比较容易的。

  1. 首先打印 $excel 的所有方法

直接打印为 {},可通过 for in

for(let method in $excel) {
    console.log(method)
}

__vars
__methods
__type
__value
__id
toString
valueOf
  1. 依次打印这些成员

发现 __methods 可能是所有方法集合:

console.log($excel.__methods)

{
QueryInterface: {
  name: 'QueryInterface',
  dispid: 1610612736,
  invkind: 1,
  flags: 1,
  argcnt: 2
},
AddRef: {
  name: 'AddRef',
  dispid: 1610612737,
  invkind: 1,
  flags: 1,
  argcnt: 0
},
Release: {
  name: 'Release',
  dispid: 1610612738,
  invkind: 1,
  flags: 1,
  argcnt: 0
},
GetTypeInfoCount: {
  name: 'GetTypeInfoCount',
  dispid: 1610678272,
  invkind: 1,
  flags: 1,
  argcnt: 1
},
GetTypeInfo: {
  name: 'GetTypeInfo',
  dispid: 1610678273,
  invkind: 1,
  flags: 1,
  argcnt: 3
},
GetIDsOfNames: {
  name: 'GetIDsOfNames',
  dispid: 1610678274,
  invkind: 1,
  flags: 1,
  argcnt: 5
},
Invoke: {
  name: 'Invoke',
  dispid: 1610678275,
  invkind: 1,
  flags: 1,
  argcnt: 8
},
Application: { name: 'Application', dispid: 148, invkind: 2, flags: 0, argcnt: 0 },
Creator: { name: 'Creator', dispid: 149, invkind: 2, flags: 0, argcnt: 0 },
Parent: { name: 'Parent', dispid: 150, invkind: 2, flags: 0, argcnt: 0 },
ActiveCell: { name: 'ActiveCell', dispid: 305, invkind: 2, flags: 0, argcnt: 0 },
ActiveChart: { name: 'ActiveChart', dispid: 183, invkind: 2, flags: 0, argcnt: 0 },
ActiveDialog: {
  name: 'ActiveDialog',
  dispid: 815,
  invkind: 2,
  flags: 64,
  argcnt: 0
},
...

可以只打印方法名称方便查找

console.log(Object.keys($excel.__methods))

[
    'QueryInterface',         'AddRef',             'Release',
    'GetTypeInfoCount',       'GetTypeInfo',        'GetIDsOfNames',
    'Invoke',                 'Application',        'Creator',
    'Parent',                 'ActiveCell',         'ActiveChart',
    'ActiveDialog',           'ActiveMenuBar',      'ActivePrinter',
    'ActiveSheet',            'ActiveWindow',       'ActiveWorkbook',
    'AddIns',                 'Assistant',          'Calculate',
    'Cells',                  'Charts',             'Columns',
    'CommandBars',            'DDEAppReturnCode',   'DDEExecute',
    'DDEInitiate',            'DDEPoke',            'DDERequest',
    'DDETerminate',           'DialogSheets',       'Evaluate',
    '_Evaluate',              'ExecuteExcel4Macro', 'Intersect',
    'MenuBars',               'Modules',            'Names',
    'Range',                  'Rows',               'Run',
    '_Run2',                  'Selection',          'SendKeys',
    'Sheets',                 'ShortcutMenus',      'ThisWorkbook',
    'Toolbars',               'Union',              'Windows',
    'Workbooks',              'WorksheetFunction',  'Worksheets',
    'Excel4IntlMacroSheets',  'Excel4MacroSheets',  'ActivateMicrosoftApp',
    'AddChartAutoFormat',     'AddCustomList',      'AlertBeforeOverwriting',
    'AltStartupPath',         'AskToUpdateLinks',   'EnableAnimations',
    'AutoCorrect',            'Build',              'CalculateBeforeSave',
    'Calculation',            'Caller',             'CanPlaySounds',
    'CanRecordSounds',        'Caption',            'CellDragAndDrop',
    'CentimetersToPoints',    'CheckSpelling',      'ClipboardFormats',
    'DisplayClipboardWindow', 'ColorButtons',       'CommandUnderlines',
    'ConstrainNumeric',       'ConvertFormula',     'CopyObjectsWithCells',
    'Cursor',                 'CustomListCount',    'CutCopyMode',
    'DataEntryMode',          'Dummy1',             'Dummy2',
    'Dummy3',                 'Dummy4',             'Dummy5',
    'Dummy6',                 'Dummy7',             'Dummy8',
    'Dummy9',                 'Dummy10',            'Dummy11',
    '_Default',               'DefaultFilePath',    'DeleteChartAutoFormat',
    'DeleteCustomList',
    ... 236 more items
]
  1. 通过名称发现 AskToUpdateLinks 这个接口比较像

在接口详细中,发现 argcnt 只需要一个参数,很有可能是 true/false 控制参数

AskToUpdateLinks: {
    name: 'AskToUpdateLinks',
    dispid: 992,
    invkind: 4,
    flags: 0,
    argcnt: 1
},
  1. 调用此参数,更改代码并测试

测试后发现工作正常,无更新不安全链接的对话框弹出

const $excel = new winax.Object("Excel.Application", { activate: false });
$excel.displayAlerts = false
$excel.AskToUpdateLinks = false
$excel.visible = true

总结

js调用ActiveX/COM+与windows程序通过时,对象的所有接口都都可以通过此方法查询到接口,比如读、取值接口:

export const setCellValue = ($excel: any, sheet: string, row: number, col: number, value: string | number) => {
    $excel.worksheets.item(sheet).cells.item(row, col).value = value
}

export const getCellValue = ($excel: any, sheet: string, row: number, col: number) => {
    const value = $excel.worksheets.item(sheet).cells.item(row, col).Text
    return value.trim()
}

对于一些参数较多的方法,比如 saveAsHtml,可以网上搜索 powershell/vba 这样同样调用COM+接口的语言,查询到示例代码,然后将对应的参数翻译到 node.js 即可,比如excel保存成 html 所需要的参数如下:

export const saveAsHtml = ($workbook: any, htmlPath: string) => {
    $workbook.SaveAs(htmlPath, 44, undefined, undefined, false, false, 1, 2);
}








 热门文章 - 分享最多
  1. node.js中用typescript连接mongodb数据并设置断开后自动重启连接
  2. git 将本地仓库关连并push远程
  3. 在Windows10上创建node.js开机启动脚本服务Task Scheduler failed to start: Error Value: 2147943711.
  4. Windows和MacOS获取当前Active Directory域的用户名和AD服务器域名
  5. JavaScript通过toLocalString格式化format各个国家本地日期时间
  6. puppeteer窗口最大化及改变窗口大小
  7. 使用node.js\Express\TypeScript\Nodemon和EsLint创建项目,并通过babel导入import绝对路径
  8. Rust 中的闭包及捕获上下文环境变量使用和更改及闭包的引用
  9. Flex布局基础概念及入门实例教程
  10. 纯CSS实现圆形动画进度百分比饼图Percentage Circle with Animation

 相关阅读
  1. node.js使用TensorFlow入门教程二:什么是张量神经网络运算与矩阵的关系及基本入门代码
  2. node.js使用TensorFlow入门教程一:简介及工作原理环境安装及初始化
  3. node.js用saml2连接Identity Provider服务器完成Azure AD/Active Directory域帐号身份认证
  4. 用Node.JS写一个简单版的类似pm2\forever的守护进程并记录错误日志
  5. NodeJS在Windows上使用OLE/COM/ActiveXObject对象连接ADODB数据库,操作Application.Excel、运行VBA宏并另存为网页
  6. MongoDB起步入门教程使用Node.JS的Promise方式查找数据
  7. Node.JS连接MySQL数据库执行增删改查提示ER_NOT_SUPPORTED_AUTH_MODE: Client does not support;如何在@mysql/xdevapi执行SQL
  8. node.js中async/await不用try/catch,使用error first或go语言方法处理异常
  9. JavaScript和node.js内存泄露的原因和避免方法及Chrome调试工具使用教程
  10. node.js性能压力测试入门教程:wrk和loadtest安装使用

  开源的 OurJS
OurJS开源博客已经迁移到 OnceOA 平台。

  关注我们
扫一扫即可关注我们:
OnceJS

OnceOA