发布:2023/12/7 15:45:52作者:大数据 来源:大数据 浏览次数:440
C#操作Excel写入宏代码到VBA中
|
String sCode = "Sub msg()\r\n" + " MsgBox \"Hello world\"\r\n" + "end Sub"; var workbook = Globals.ThisAddIn.Application.ActiveWorkbook; var oModule = workbook.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule); oModule.Name = "Module1"; //在模块中添加VBA代码 oModule.CodeModule.AddFromString(sCode); //在ThisWorkbook中添加VBA代码 workbook.VBProject.VBComponents.Item(1).CodeModule.AddFromString(sCode); MessageBox.Show("ok"); |
参考微软官方文档:
https://docs.microsoft.com/zh-cn/visualstudio/vsto/walkthrough-calling-code-in-a-vsto-add-in-from-vba?view=vs-2019
错误异常:
System.Runtime.InteropServices.COMException:“不信任到 Visual Basic Project 的程序连接”
System.Runtime.InteropServices.COMException
HResult=0x800A03EC
Message=不信任到 Visual Basic Project 的程序连接
Source=<无法计算异常源>
StackTrace:
<无法计算异常堆栈跟踪>
解决办法:根据对应的office版本找以下对应选项
将Excel中的开发工具选项卡,点击安全性,宏设置为信任,在开发人员宏设置,选中信任对VBA工程对象模型的访问。
在文件,选项,找到信任中心,信任中心设置,宏设置,其它操作如上。
打开Excel-》工具-》宏-》安全性-》可靠发行商,选中“信任对于Visiual Basic 项目的访问”,按确定即可。
当Excel保存时添加相应的事件动作:
|
private void ThisAddIn_Startup(object sender, System.EventArgs e) { Globals.ThisAddIn.Application.WorkbookAfterSave += Application_WorkbookAfterSave; } private void Application_WorkbookAfterSave(Excel.Workbook Wb, bool Success) { ImportExportChecker.SiteHelper.WorkbookAfterSave(Wb); } |
VBA调用VSTO中DLL或类库方法或函数
下面代码的ExcelAddInApp为项目名称或插件名称
|
Sub CallVSTOMethod() Dim addIn As COMAddIn Dim automationObject As Object Set addIn = Application.COMAddIns("ExcelAddInApp") Set automationObject = addIn.Object automationObject.ExportCsvData Application.ActiveWorkbook End Sub |
C#代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Linq; using Excel = Microsoft.Office.Interop.Excel; using ImportExportChecker; namespace ExcelAddInApp { public partial class ThisAddIn { private AddInUtilities utilities; protected override object RequestComAddInAutomationService() { if (utilities == null) utilities = new AddInUtilities(); return utilities; } private void ThisAddIn_Startup(object sender, System.EventArgs e) { } private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { } #region VSTO 生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要修改 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InternalStartup() { this.Startup += new System.EventHandler(ThisAddIn_Startup); this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown); } #endregion } } |
类库代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
using ImportExportChecker; using Microsoft.Office.Interop.Excel; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace ImportExportChecker { [ComVisible(true)] public interface IAddInUtilities { void ExportCsvData(Workbook workbook); } [ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] public class AddInUtilities : IAddInUtilities { // This method tries to write a string to cell A1 in the active worksheet. public void ExportCsvData(Workbook workbook) { SiteHelper.ShowExclamation(workbook.Name); ImportExportChecker.SiteHelper.WorkbookAfterSave(workbook); } } } |
C# 得到EXCEL表格中的有效行数和列数
每种方法中上面的是Excel的行数,下面的是Excel的列数。方法七:经过加工修改已经可以读出来的是有效数据行
using Excel = Microsoft.Office.Interop.Excel;//Excel表读写
Excel.Application app = new Excel.Application();
object omissing = System.Reflection.Missing.Value;
Excel.Workbook workbook = app.Workbooks.Open(excleItem.FullName, omissing, omissing, omissing, omissing, omissing, omissing, omissing, omissing, omissing, omissing, omissing, omissing, omissing, omissing);
Excel.Sheets sheets = workbook.Worksheets;//读取Excel表格的标签页
Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//读取第一张表
方法1:
worksheet.UsedRange.Rows.Count
worksheet.UsedRange.Columns.Count
缺点:有时可能会比实际数大一些,原因是如果你把最后几行(列)数据清除后(非整行或整列删除),用这个命令仍返回未清除前的值。就是说现在虽然是空的,但是你曾经用过也算你的。
方法2:
worksheet.Range(“A65535″).End(xlUp).Row
worksheet.Range(“IV1″).End(xlToLeft).Column
可以简写为:
worksheet.[A65536].End(xlUp).Row
worksheet.[IV1].End(xlToLeft).Column
缺点:只能计算出一列(行)的最后一个单元格所在的行(列)数。本例是只返回A列最后一个单元格所占的行数。
方法3:
worksheet.Cells.SpecialCells(xlCellTypeLastCell).Row
worksheet.Cells.SpecialCells(xlCellTypeLastCell).Column
缺点:在工作表进行对删除或清除操作时也会变得比实际情况大。
方法4:
worksheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row
worksheet.UsedRange.SpecialCells(xlCellTypeLastCell).Column
缺点:在工作表进行对删除或清除操作时也会变得比实际情况大。
方法5:
worksheet.CountA(ActiveSheet.Range(“A:A”))
worksheet .CountA(ActiveSheet.Range(“1:1″))
只能统计一列(行)的实际使用情况,得到的不一定是最后一行(列)的位置。方法2的数值比此方法大时,说明在A列的数据间有空白未填写的单元格。
方法6:
worksheet.Cells.Find(What:=”*”, After:=[A1], SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
worksheet.Cells.Find(What:=”*”, After:=[A1], SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
效果同方法2
方法7:
worksheet.UsedRange.CurrentRegion.Rows.Count
worksheet.UsedRange.CurrentRegion.Columns.Count
缺点:CurrentRegion 所在位置的活动区域,若有空行或者空列,则空行或空列后面的无法获取到
C#获取Excel列名或column名称
string columnName = worksheet.Cells[3, 1].Address.Replace("$","");
vba中注释:
'或rem
vba中sub和function调用及区别:
sub无返回值,function可以有/无返回值
若要从其他过程中调用某个 Sub 过程,请键入该过程的名称并包含任何所需的参数值。 不需要使用 Call 语句,但如果使用了该语句,则必须将任何参数包含在圆括号内。
一个参数及多个参数
|
Sub Main() MultiBeep 56 Message End Sub Sub MultiBeep(numbeeps) For counter = 1 To numbeeps Beep Next counter End Sub Sub Message() MsgBox "Time to take a break!" End Sub |
|
Sub Main() HouseCalc 99800, 43100 Call HouseCalc(380950, 49500) End Sub Sub HouseCalc(price As Single, wage As Single) If 2.5 * wage <= 0.8 * price Then MsgBox "You cannot afford this house." Else MsgBox "This house is affordable." End If End Sub |
在调用 Function 过程时使用圆括号
若要使用函数的返回值,请将该函数分配给变量并将参数包含在圆括号内,如以下示例所示。
Answer3 = MsgBox("Are you happy with your salary?", 4, "Question 3")
如果对函数的返回值不感兴趣,则可以按照调用 Sub 过程的同样方式调用函数。 省略圆括号,列出参数,且不要将函数分配给变量,如以下示例所示。
MsgBox "Task Completed!", 0, "Task Box"
Sub 或 Function 过程中的语句可使用命名参数将值传递给所调用的过程。 您可以按照任何顺序列出命名参数。 命名参数包含参数的名称后跟一个冒号和一个等号 (:=) 以及分配给该参数的值。
以下示例使用命名参数调用 MsgBox 函数,而不返回任何值。
MsgBox Title:="Task Box", Prompt:="Task Completed!"
以下示例使用命名参数调用 MsgBox 函数。 将返回值分配给变量。_下划线为行连接
answer3 = MsgBox(Title:="Question 3", _
Prompt:="Are you happy with your salary?", Buttons:=4)
关于证书pfx和cer证书:
1.带有私钥的证书
由Public Key Cryptography Standards #12,PKCS#12标准定义,包含了公钥和私钥的二进制格式的证书形式,以pfx作为证书文件后缀名。
2.二进制编码的证书
证书中没有私钥,DER 编码二进制格式的证书文件,以cer作为证书文件后缀名。
3.Base64编码的证书
证书中没有私钥,BASE64 编码格式的证书文件,也是以cer作为证书文件后缀名。
pfx两个要点:
1、pfx 文件中包含私钥与公钥和证书
|
别人要是问<span class="token punctuation">.</span>pfx文件里放的是啥,你可以直白的说告诉他里面放的就是公钥和私钥和证书。 |
2、pfx 有访问密码保护
- 私钥不能随便让人查看,访问密码是为了进行安全控制。
- 即使pfx文件被别人得到,没有访问密码也较难获取私钥。
由定义可以看出,只有pfx格式的数字证书是包含有私钥的,cer格式的数字证书里面只有公钥没有私钥。
在pfx证书的导入过程中有一项是“标志此密钥是可导出的。这将您在稍候备份或传输密钥”。一般是不选中的,如果选中,别人就有机会备份你的密钥了。如果是不选中,其实密钥也导入了,只是不能再次被导出。这就保证了密钥的安全。
如果导入过程中没有选中这一项,做证书备份时“导出私钥”这一项是灰色的,不能选。只能导出cer格式的公钥。如果导入时选中该项,则在导出时“导出私钥”这一项就是可选的。
如果要导出私钥(pfx),是需要输入密码的,这个密码就是对私钥再次加密,这样就保证了私钥的安全,别人即使拿到了你的证书备份(pfx),不知道加密私钥的密码,也是无法导入证书的。相反,如果只是导入导出cer格式的证书,是不会提示你输入密码的。因为公钥一般来说是对外公开的,不用加密
------------ pfx密钥 -----------
公钥 加密+验证签名
私钥 解密+签名
pfx 本来就不应该在网络上传播.. 生成新的客户端证书只需要传 CSR, CER .. 正确的过程应该是:
客户端: 生成私钥, 填写证书相关信息 CN/O/OU/EMail 等等, 用 私钥生成 证书请求 CSR ..
把 CSR 通过网络发给 CA
CA: 对 CSR 进行签名, 生成 CER
CA 把证书发送回来
客户端: 打包私钥 + CER 为 PKCS#12 (pfx) 文件.
整个过程都不会传递私钥.
how to convert cert
understanding pfx file
understanding pfx file
关于Visual Studio 2010 Tools for Office Runtime简称(VSTO)
cmd执行提示如下异常:
'VSTOInstaller.exe' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
PS C:\Windows\system32> VSTOInstaller.exe
VSTOInstaller.exe : 无法将“VSTOInstaller.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如
果包括路径,请确保路径正确,然后再试一次。
所在位置 行:1 字符: 1
+ VSTOInstaller.exe
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (VSTOInstaller.exe:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
VSTOInstaller默认安装路径:
c:\Program Files\Common Files\microsoft shared\VSTO\10.0>
首先在默认路径下找,如果没有到微软官方下载:https://www.microsoft.com/en-us/download/details.aspx?id=56961
参数说明:
VSTOInstaller.exe 10.0.60828.0
© Microsoft Corporation. All rights reserved.
VSTOInstaller.exe [[/install <URL> ] | [/uninstall <URL>]] [/silent] [/help]
/install, /i: 安装解决方案。此选项后面必须是部署清单的完全限定路径,其形式为“http://”、“https://”或“\\服务器名\文件夹名”。
/uninstall, /u: 卸载解决方案。此选项后面必须带有部署清单的完全限定路径,其形式为“http://”、“https://”或“\\服务器名\文件夹名”。
/silent, /s: 在不提示输入或提供信息的情况下安装或卸载。
vsto实现静默安装
|
cd 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.17134.0\x64' .\certmgr.exe -add -c "C:\TestDemo_TemporaryKey.pfx" -s -r localMachine root .\certmgr.exe -del -c -n "LENOVO-PC\ThinkPad" -s -r localMachine root cd 'c:\Program Files\Common Files\microsoft shared\VSTO\10.0' .\VSTOInstaller.exe /I "C:\Users\ThinkPad\source\repos\ExcelAddInTestDemo\ExcelAddInTestDemo\publish\ExcelAddInTestDemo.vsto" /S .\VSTOInstaller.exe /U "C:\Users\ThinkPad\source\repos\ExcelAddInTestDemo\ExcelAddInTestDemo\publish\ExcelAddInTestDemo.vsto" /S |
C# Excel快速填充数据,excel快速读取数据、excel快速导入数据
利用for循环实现单元格cell填充堪称龟速,太慢了,可以用Range.Value实现二维定长数组,直接填充数据,二维可变数组不适用。
具体代码如下:
for循环逐个填充cells
|
for (int i = 0; i < rows.Length; i++) { var list = rows[i].Split(','); for (int j = 0; j < list.Length; j++) { worksheet.Cells[row, i + 1] = 123; } } |
利用二维数组实现
|
var rows = csvData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); int rowCount = rows.Length; int colCount = rows[0].Split(',').Length; string[,] data = new string[rowCount, colCount]; for (int i = 0; i < rows.Length; i++) { var list = rows[i].Split(','); for (int j = 0; j < list.Length; j++) { data[i, j] = list[j]; } } worksheet.Range["A1"].Resize[rowCount, colCount].Value2 = data; |
声明:本站内容来源于原创和互联网,尊重作者版权,转载请注明来源网址,欢迎收藏,谢谢!