lxlzmh2002 lxlzmh2002
关注数: 172 粉丝数: 75 发帖数: 2,388 关注贴吧数: 10
[EXCEL] VBA 批量处理数据文件按内容进行拆分并保存到指定路径 批量读取数据源文件 按内容拆分不同文件,分发在保存不同路径下 对处理完成的数据源进行归档 ------------------------------------------------------------------------ Global fsoSub DistributeBillings() 'get source files' folder path sfp = Sheet2.Cells(1, 2) If Len(sfp) = 0 Then sfp = ThisWorkbook.Path If Right(sfp, 1) <> "\" Then sfp = sfp & "\" 'get archive folder path Set fso = CreateObject("Scripting.FileSystemObject") If Not fso.folderexists(sfp & "Archive") Then fso.CreateFolder (sfp & "Archive") afp = sfp & "Archive\" 'create dictionary of matrix Set dd = CreateObject("Scripting.Dictionary") arr = Sheet2.Cells(3, 1).Resize(Sheet2.[A1000000].End(xlUp).Row - 2, 2) For i = 1 To UBound(arr, 1) If Right(arr(i, 2), 1) <> "\" Then arr(i, 2) = arr(i, 2) & "\" dd(arr(i, 1)) = arr(i, 2) Next 'remove old sheets, if any Application.DisplayAlerts = False For i = Sheets.Count To 3 Step -1 Sheets(Sheets.Count).Delete Next 'get list of all source files Sheet1.Range("A2").Resize(10000, 14).ClearContents GetAllFiles (sfp) For i = 2 To Sheet1.[A100000].End(xlUp).Row 'open one of souce files ff = Sheet1.Cells(i, 1) fn = fso.GetFileName(ff) Set wb = Workbooks.Open(ff) ' check if exist non-registered company code rs = ActiveSheet.Cells(10000, 9).End(xlUp).Row For x = 2 To rs If Not dd.exists(ActiveSheet.Cells(x, 9).Value) Then MsgBox "File:" & fn & " Code:º " & ActiveSheet.Cells(x, 9).Value & " is not existed in distribution matrix,retry after update it please!" wb.Close GoTo ex End If Next ' copy source file data to sheet For x = 2 To rs Notes = wb.Sheets(1).Cells(x, 9).Value If Not Exist(Notes) Then ThisWorkbook.Activate Set st = Sheets.Add(After:=Sheets(Sheets.Count)) st.Name = Notes wb.Sheets(1).[A1:AG1].Copy st.[A1] Else Set st = Sheets(Notes) End If wb.Sheets(1).Cells(x, 1).Resize(1, 33).Copy st.[A100000].End(xlUp)(2) DoEvents Next wb.Close ' save sheet to file For c = 3 To Sheets.Count sn = Sheets(c).Name Sheets(c).Copy tf = dd(sn) & fn ActiveWorkbook.SaveAs Filename:=tf ActiveWorkbook.Close DoEvents Next 'archive source file fso.CopyFile ff, afp Kill ff For c = Sheets.Count To 3 Step -1 Sheets(Sheets.Count).Delete Next ex: Next Application.DisplayAlerts = True End Sub Function GetAllFiles(fp$) Dim fn, n n = Dir(fp & "\") Do While Len(n) <> 0 If UCase(n) Like "*.XLS" Or UCase(n) Like "*.XLSX" Then Sheet1.[A65536].End(3)(2) = fp & "\" & n Sheet1.Hyperlinks.Add anchor:=Sheet1.[A65536].End(3)(1), Address:=fp & "\" & n End If n = Dir Loop For Each fn In fso.getfolder(fp).subfolders GetAllFiles (fn) Next End Function Function Exist(sht) As Boolean Exist = False For Each s In Sheets If s.Name = sht Then Exist = True Exit For End If Next End Function 案例下载:http://tieba.baidu.com/mo/q/checkurl?url=https%3A%2F%2Fpan.baidu.com%2Fs%2F1sGfG5QZ5smcQADLXfh843A%3Fpwd%3Dt18q&urlrefer=bd473e73329286719fda8501a234ce25 此例多次使用FSO对象的方法,参见此贴 https://tieba.baidu.com/p/8848588841 的 91楼
[分享] Excel不同子文件夹内的多个文件进行汇总 背景: 1. 被汇总的数据源Excel文件,分布在不同层级的子文件夹当中 2. 每个数据源Excel文件叫不同的名字,每个文件含有不同的工作表名字 3. 需要被汇总的工作表,有相同的格式 Public fso Sub ListFiles() ' 汇总 Set fso = CreateObject("Scripting.FileSystemObject") Sheet1.Range("A2").Resize(10000, 14).ClearContents GetAllFiles (ThisWorkbook.Path) '对Excel文件及子目录中的文件,进行列表 r = 2 For i = 2 To Sheet1.[A100000].End(xlUp).Row '循环打开每个列表上的Excel文件 Set wb = Workbooks.Open(Sheet1.Cells(i, 1)) For Each s In wb.Sheets '遍历当前文件所有工作表 Set c = s.[B:B].Find(What:="No.") ' 查找格式数据是否存在 If c Is Nothing Then GoTo nx '不存在继续下一个表 For k = c.Row + 1 To s.[B100000].End(xlUp).Row '读表到汇总页 Sheet1.Cells(r, 2) = Sheet1.Cells(i, 1) Sheet1.Cells(r, 3) = s.Name Sheet1.Cells(r, 4) = s.Cells(k, 2) Sheet1.Cells(r, 5) = s.Cells(k, 3) Sheet1.Cells(r, 6) = s.Cells(k, 4) Sheet1.Cells(r, 7) = s.Cells(k, 5) Sheet1.Cells(r, 8) = s.Cells(k, 6) Sheet1.Cells(r, 9) = s.Cells(k, 7) Sheet1.Cells(r, 10) = s.Cells(k, 8) Sheet1.Cells(r, 11) = s.Cells(k, 9) Sheet1.Cells(r, 12) = s.Cells(k, 10) DoEvents r = r + 1 Next nx: Next Application.DisplayAlerts = False wb.Close Application.DisplayAlerts = True Next End Sub Function GetAllFiles(fp$) ' 对当前目录及所有子目录中的Excel文件列表 Dim fn, n n = Dir(fp & "\") Do While Len(n) <> 0 If UCase(n) Like "*.XLS" Or UCase(n) Like "*.XLSX" Then Sheet1.[A65536].End(3)(2) = fp & "\" & n Sheet1.Hyperlinks.Add anchor:=Sheet1.[A65536].End(3)(1), Address:=fp & "\" & n End If n = Dir Loop For Each fn In fso.getfolder(fp).subfolders GetAllFiles (fn) Next End Function 上述vba代码,除了使用变量、循环判断基本语句之外,剩下的80%都是在使用Excel的对象属性和方法。 那,学好使用对象属性和方法,是不是掌握了VBA的80%, 可以这样说吗? 本例中使用的对象的属性和方法,全部记录在下贴之中: #EXCEL VBA对象的常用操作方法c# - https://tieba.baidu.com/p/8848588841
[原码分享] - VBA通过LDAP协议提取域用户信息 本例是VBA代码,通过LDAP协议提取域内任意用户的信息,如:姓名,职务,部门,公司,电话,邮箱,地址等等。 前提条件:1. 公司的电脑已加域管理,2.人员相关信息已登记在域目录中 名词解释: 域管理 - 企业标准化应用,对在加域计算上登陆的用户作身份检验。 活动目录 - 域能作身份验证的基础,是域控服务器上有用户的数据库,此数据库叫活动目录。 LDAP - 轻量级目录访问协议,通过它可以访问域活动目录中的信息。所有加域的计算机默认支持LDAP协议 怎么知道计算机是否已加域? 简单地说,在计算机属性中查看,如果计算机名称和全名一模一样,则未加域。如果在全名中多了一些".XXX.XXX"的后缀,则是加域计算机。 怎么使用? 一.先用VBA写个自定义函数,如下 Function GetUserInfo(ByVal SearchField As String, ByVal SearchString As String, ByVal ReturnField As String) As String Set Conn = CreateObject("ADODB.Connection") Conn.Open "Provider=ADsDSOObject;" DM = GetObject("LDAP://rootDSE").Get("defaultNamingContext") Set CMD = CreateObject("ADODB.Command") CMD.ActiveConnection = Conn CMD.CommandText = ";(&(objectCategory=User)" & "(" & SearchField & "=" & SearchString & "));" & SearchField & "," & ReturnField & ";subtree" Set rs = CMD.Execute If rs.RecordCount = 0 Then GetUserInfo = "查无此人" Else GetUserInfo = rs.Fields(ReturnField) End If Conn.Close: Set rs = Nothing: Set CMD = Nothing: Set Conn = Nothing End Function 二.在Excel单元格公式中调用上述函数,例如: =GetUserInfo("sAMAccountName",A2,"name") - 意思是在域目录中查找sAMAccountName 等于A2单元格的值, 返回目录中它的Name,本例A2单元格内容是用户的ID *** sAMAccountName, Name 都是目录中固定名称,不可改。sAMAccountName相当于用户ID, Name即名字 =GetUserInfo("sAMAccountName",A2,"title") - 根据ID查职务,A2是具体用户的ID =GetUserInfo("sAMAccountName",A2,"company") - 根据ID查职务,A2是具体用户的ID =GetUserInfo("sAMAccountName",A2,"department")- 根据ID查部门 =GetUserInfo("sAMAccountName",A2,"telephonenumber")- 根据ID查电话号码 =GetUserInfo("sAMAccountName",A2,"mail") - 根据ID查职务邮箱地址 =GetUserInfo("sAMAccountName",A2,"manager") - 根据ID查直属经理名字 =GetUserInfo("sAMAccountName",A2,"streetAddress")- 根据ID查住址 注:并不是一定要根据sAMAccountName去查人员的其他信息,原则上可以根据目录已有任意字段,去查其他任意字段。 更多LDAP可查阅的域用户信息字段,请参阅下贴的第133楼: #EXCEL VBA对象的常用操作方法c# https://tieba.baidu.com/p/8848588841
【转载】VBA代码的调试和错误处理 左丘明说:"人非圣贤, 孰能无过? 过而能改, 善莫大焉",他还说:"视已非而不自见,专窥人眚以为能,斯乃鄙恶之人也"。 翻译一下,他说人都不是神仙, 写VBA代码没有人能一遍过, 重点是你得学会调试, 出错了懂得修改,然后就比抽几口烟还舒服了。 他还说,从来看不见自己错, 专门挑他人的错误 并以此当能耐的, 揩是衰仔。 本贴大致分如下三个部分,如果您已经是位神仙了,麻烦您出门向右转弯。 【一】错误种类与描述 【二】代码调试与排错 【三】错误处理 ------------------------------------------- 【一】错误种类与描述: 编译错误,此时代码还未执行,VBE提示输入的代码存在有语法错误 运行错误, 运行时才会出现的错误,错误一般是与待处理的数据相关,或者与数据的处理方法有关 逻辑错误,很可能代码执行正常,但是结果不符合目标 错误代码及含义: 3 无Go Sub返回 5 无效的过程调用或参数 6 溢出 7 内存溢出 9 下标越界 10 该数组被固定或暂时锁定 11 除数为零 13 类型不匹配 14 溢出串空间 16 表达式太复杂 17 不能执行所需的操作 18 出现用户中断 20 无错误恢复 28 溢出堆栈空间 35 子过程或函数未定义 47 DLL应用程序客户太多 48 加载DLL错误 49 DLL调用约定错误 51 内部错误 52 文件名或文件号错误 53 文件未找到 54 文件模式错误 55 文件已打开 57 设备IO错误 58 文件已存在 59 记录长度错误 61 磁盘已满 62 输入超出文件尾 63 记录号错误 68 设备不可用 70 拒绝的权限 74 不能更名为不同的驱动器 75 路径/文件访问错误 76 路径未找到 91 对象变量或With块变量未设置 92 For循环未初始化 93 无效的模式串 94 无效使用Null 96 由于对象已经激活了事件接收器支持的最大数目的事件,不能吸收对象的事件 97 不能调用对象的友元函数,该对象不是所定义类的一个实例 98 属性或方法调用不能包括对私有对象的引用,不论是作为参数还是作为返回值 321 无效文件格式 322 不能创建必要的临时文件 325 资源文件中格式无效 380 无效属性值 381 无效的属性数组索引 382 运行时不支持Set 383 (只读属性)不支持Set 385 需要属性数据索引 387 Set 不允许 393 运行时不支持Get 394 (只读属性)不支持Get 422 属性没有找到 423 属性或方法未找到 424 要求对象 430 类不支持自动化(Automation)或不支持期待的接口 432 自动化(Automation)操作时文件名或类名未找到 438 对象不支持该属性或方法 440 自动化(Automation)错误 442 远程控制到类型库或对象库的连接丢失,按下对话框的[lbk]lbk[rbk]确定[lbk]rbk[rbk]按钮取消引用 443 Automation对象无缺省值 445 对象不支持该动作 446 对象不支持命名参数 447 对象不支持当前的本地设置 448 未找到命名参数 449 参数不可选 450 Protperty过程未定义,Property get 过程未返回对象 452 无效的序号 453 指定的DLL函数未找到 454 代码资源未找到 455 代码资源锁定错误 457 该关键字已经与该集合的一个无素相关联458 变量使用了一个Visual Basic不支持的自动化(Automation)类型 459 对象或类不支持的事件集 460 无效的剪贴板格式 461 方法和数据成员未找到 462 远程服务器不存在或不可用 463 类未在本地机器上注册 481 无效的图片 482 打印机错误 735 不能将文件保存到TEMP 744 要搜索的文本没有找到 746 替换文件太长 1004 应用程序定义或对象定义错误
数据字典的使用方法 字典:是Key+Item的集合。Key是具有唯一性的关键字,Item是关键字所对应的值。 创建字典:Set d = CreateObject("Scripting.Dictionary"), 创建一个名字为D的空字典。 常用方法: d.add"lxlzmh2002", "Excel梦想之家" : 向d字典添加一条关键字是lxlzmh2002, 值为Excel梦想之家的字典纪录。- 可以简写为: d("lxlzmh2002")="Excel梦想之家" d.Exists("lxlzmh2002"): 检查d字典是否存在关键字为lxlzmh2002的纪录,返回True或False d.Remove("lxlzmh2002"): 从d字典上删除关键字为lxlzmh2002的纪录 d.RemoveAll: 清空d字典纪录 d.Keys: 返回d字典的所有关键字,值为数组d.Items: 返回d字典的所有值,值为数组 常用属性: d.Count: 返回d字典中纪录的个数d.Key("lxlzmh2002")="lxlzmh2024": 将d字典的关键字lxlzmh2002更改为新的关键字d.Item("lxlzmh2002")="Excel梦想之国" : 将d字典上关键字为lxlzmh2002纪录的值更改为新值,简写d("lxlzmh2002")="Excel梦想之国" 字典的item值,可以是单值,也可以是数组,如:d("lxlzmh2002")=array("Excel梦想之家","Excel梦想之村","Excel梦想之镇") 但是,字典值为多个值并非是一定要用数组,可以让d("lxlzmh2002")="Excel梦想之家|Excel梦想之村|Excel梦想之镇"在实际使用时,用split分开:split(d.Key("lxlzmh2002"),"|") - split结果是数组。 字典由于索引的存在,在数据查询上是非常高效的。关于字典的详解,请参阅:
VBA对象的常用操作方法c# [单元格]对象的表示方法 表示第一个工作表的A2单元格对象,有三种下面常用的表示方法: 第一种:Sheets(1).Range("A2") - 适合一次性引用,不太适合用变量遍历 第二种:Sheets(1).[A2] - 书写简单,适合一次性引用,不适合遍历 第三种:Sheets(1).Cells(2,1) - 适用于变量改变行列值,用于循环遍历。 [工作表]对象的表示方法 worksheets("test") : 表示表名为test的工作表对象,可以简写为sheets("test") - 适用已知表名的调用 worksheets(1) : 表上工作薄上第1个工作表对象,可以简写为sheets(1) - 适用不知表名,但已第几个表的调用 sheet1: 表示VBE (Alft + F11) 编程环境,表name属性为sheet1的工作表 -这是vba工程内部工作表的属性名,不受工作表名变动,工作表顺序变动影响。推荐程序使用表属性名。如果有多个EXCEL工作薄打开,sheet1指的是代码所在那个工作薄上的sheet1表 -activesheet : 表示当前处理活动状态的工作表对象 适用于在未知表名字,未知表位置顺序下,对当表工作表的调用 [工作薄]对象的表示方法 workbooks("test"):表示名为test的工作薄 - 适用于已知Excel文件名称的访问 workbooks(1):表示第1个索引顺序的工作薄 - 适用于对已知Excel文件打开顺序的访问 activeworkbook:表示当前的活动工作薄 - 适用对当前活动工作薄的访问,即可能未知文件名称或者文件打开顺序的的前提下,用activeworkbook来访问当前活动的工作薄。 thisworkbook:表示VBA代码所在的工作薄 - 适用对VBA代码所在工作薄的访问 [application] 对象 application - 就Excel而言,application表示的就是Excel软件本身的对象,前边所述的单元格,工作表,工作薄对象,都历属于application的属性,除此之外它还有些在对软件的操作层面的属性和方法,详文在后讨论application的属性和方法时再说。 一直在说属性和方法,他俩究竟是指什么? 属性 - 描述对象特征,通常是个名词。属性的值可以描述名字,颜色,长度等等。改变了属性的值,相当于改了对象特征的量,比如:sheet1.name="vba吧",即把表一的名字改为VBA吧。需注意两点:1.有些属性是只读的,不可修改,2.属性也可能是另外一个对象。 方法 - 描述对象所能执行的动作,通常是个动词。方法通常不能改变,只能被执行,比如:工作表的打开、新建、删除等操作,都是在执行一个动作。
#EXCEL VBA对象的常用操作方法c# 在开始聊EXCEL 对象操作之前,得先简单聊一下操作这些对象的上帝之手--VBA,它是以一种上帝视角方式在工作。那什么算上帝视角?上帝视角就是非人类的视角,它不须要遵循人类的习惯来运作,打个比方,你在客厅看电视,忽然困意来习想上床睡觉,你得先起身离开客厅,打开卧室房门,才能上床睡觉,这是人类的常规操作。而上帝模式下只需要一步,当你想睡觉时,上帝可以把你从客厅直接扔到卧室的床上,穿越时间空间,这就是上帝视角。你可以在书房直接开客厅电视机开关,你可以在躺床上一边刷手机的同时,另一边在床上安排厨房炊具炒菜,这都是上帝操作。 VBA操作Excel对象就是上帝视角,不必遵循人类的操作规则。这一点新入坑VBA朋友尤为要注意,再比如说,人类的操作Excel需要眼睛可得见,而VBA操作这是不必要的,人类要复制一个单元格,得先切换到那个格所在的工作表,再找到并选中那个格,然后鼠标右键复制,VBA则可以从任何地方,对任意一个工作表上的单元格,直接一步复制。在人类层面上,操作Excel是有空间上的先后顺序,而VBA做同样的事情,由于它是上帝视角,工作表也好单元格也罢,对它来就说好象是兵器架子上的兵刃,是平行排列,不需要空间上可视,不需要先后顺序,直接使用。 那么,VBA究竟是通过什么手段来操作Excel的?它是通过操作Excel对象的属性和方法来实现的,本贴则是简述Excel对象的“常用”操作方法。 为防止走丢,请关注、点赞、收藏转发。
1 下一页