今天分享一个我自己在用的VBA小程序,我自己套用这个模板,解决了不同员工不同的需求。

  工作中,经常遇到需要从金蝶ERP中打印一些客户需要的格式的文档,还有一些内部员工自己需要的数据做分析,如果使用K3套打相对麻烦,所以一般就是用宏从K3数据库抓取数据再写入EXCEL,这样员工就能自己更新需要的数据(抓取的数据库内容基本是固定的字段,需要调整的时候不多)。

  因为每个员工要求的结果不一样,但是操作过程都是一样的,所以,从一开始对每个人写不同的程序要求,到最后总结出来这个小模板,也是方便自己管理和维护这些小程序。下面就开始介绍这个模板是如何工作的:

  一、建立EXCEL表格

  如下图,这是我给所有人设计的EXCEL模板:

   如图所示:

    1、不管员工需要得到多少个表的内容,我都是会建立一个如图中1所示的工作表名,用于区分,如果有多个,就多建几个。

    2、根据员工要求得到的结果,先建立一个范围,写上对应的字段名,再选中这个范围,创建一个“超级表”

    3、对超级表的命名,我使用统一的格式,就是用 “表_" 加上 ”工作表名“ 的格式,这主要是为了在写VBA的过程中,让程序更方便读懂。比如这个例子中,我的工作表名是 ”出货清单FromERP“ ,那我的超级表名就叫 ”表_出货清单FromERP“ ,这个地方大家根据自己的习惯来修改就行。

  二、代码

  首先,我没有使用任何的其它变量,比如需要读取某个日期范围的数据,比如读取某个单据号的数据等,这些大家可以根据自己的要求添加,全部代码如下图:(后面我还会放出代码和分析用处,这里只是让大家直观看到代码其实是很少的,但它就能完成很多的工作需求)

  下面开始讲解这段代码:

  1、全程变量

1 Public IP As String, DB As String, UID As String, PW As String
2 Public cn As Object, rs As Object
3 Public Obj As ListObject

  这里没什么需要特别说明的,就是一些需要用到的全程变量,有强迫症的也可以把一些非全程需要的变量自己改成局部变量。

  2、初始化过程

 1 Sub Ini()
2 Dim cnSQL As String
3
4 IP = "你的服务器IP"
5 DB = "你的数据库名"
6 UID = "用于访问数据库的用户名"
7 PW = "用户密码"
8
9 Set cn = CreateObject("ADODB.Connection")
10 Set rs = CreateObject("ADODB.Recordset")
11 cnSQL = "Provider=sqloledb;Server=" & IP & ";Database=" & DB & ";Uid=" & UID & ";Pwd=" & PW & ";"
12
13 If cn.State <> 1 Then
14 cn.Open cnSQL
15 End If
16
17 End Sub

  这里也没什么好介绍的,直接套用就行,这段代码我也是网上抄的。

  3、主过程

 1 Sub Process()
2 Dim StrSql As String
3
4 '----调用变量初始化
5 Call Ini
6
7 '------从导出最新的采购价格。
8 StrSql = "这里写你读取SQL的语句"
9 Call ReadFromSQL("出货清单FromERP", "表_出货清单FromERP", StrSql)
10
11 cn.Close '关闭连接
12 Set rs = Nothing '清空对象
13 Set cn = Nothing '清空对象
14
15 End Sub

  这里就是我们运行宏的时候执行的过程,它先调用了前面的初始化过程,然后需要你把SQL语句放进去,再调用一个读取SQL并写入EXCEL的过程,最后关闭连接,清空对象。

  这里的关键其实就是在第8行:StrSql = "这里写你读取SQL的语句"

  这个SQL语句呢,我们可以在相应的读取SQL的软件里调试,并根据你的要求能得到你要的结果,最后就把那一句SQL语句放在上面的双引号里就行。

  这里提示一下,有时候SQL语句会很长很长,那没关系,我们可以把SQL语句拆分成多个字符串再连接起来就行,比如写成这样

1 StrSql="字符串1" & _
2 "字符串2" & _
3 "字符串3" & _
4 ……
5 "字符串n"

  比如我就曾经写过一个8行的字符串,它需要通过很多个表关联查询并出一个结果,大概内容如下图:

  第9行这里,大家就可以一目了然了,过程引用中,变量的排列为:工作表名,超级表名,SQL字符串。

  4、从SQL读取数据,并写入EXCEL

 1 Sub ReadFromSQL(ShtName As String, objName As String, SQLStr As String)
2
3 '----选择目标表
4 Sheets(ShtName).Select
5
6 '----清除原来数据
7 With Sheets(ShtName).ListObjects(objName)
8
9 '----判断当前表格是否在筛选状态,如果是,就显示所有数据,如果不做这一步,在筛选状态下,下一步操作删除的时候会出错
10 If .AutoFilter.FilterMode = True Then
11 .AutoFilter.ShowAllData
12 End If
13
14 '----如果目标表有内容,就清空
15 If .ListRows.Count <> 0 Then
16 .DataBodyRange.Select
17 Selection.Delete
18 End If
19
20 '----读取SQL查询结果到Records记录集
21 rs.Open SQLStr, cn
22
23 If rs.EOF = True Then
24 'MsgBox "这里可以根据需要自己写出错提示"
25 Else
26 '下面的循环把查询结果写到Excel表中
27 .Range(2, 1).CopyFromRecordset rs
28 End If
29
30 End With
31
32 '----关闭记录集
33 rs.Close
34
35 End Sub

  第4行:我们要确定我们会转到需要写入数据的工作表,所以先定位好工作表

  第7-30行:通过控制超级表,来清除数据。这也里讲一下为什么要用超级表,因为使用超级表,在定位、清除数据、写入数据等,它会相应的更加灵活。

  第10-12行:这一步很关键。因为在实际使用过程中,用户有可能会把一个结果筛选,如果不加这一步,在筛选状态进行一些VBA操作,会提示出错,所以就强制的,把超级表的筛选状态变成未筛选。

  第15-18行:这里是判断,如果这个超级表不为空,那就清空它。

  第21行:把我们要的SQL语句对应的结果读取出来。

  第23-28行:把SQl查询结果,写在超级表的表体区域:.Range(2,1) 位置。

  第33行:关闭记录集。这里说一下,为什么要把这一个操作放在这,因为我们有可能会同时对多个工作表进行操作,每一个操作都会调用一次这一个过程,所以就需要在下一个调用前,把当前的记录集关闭。

  到这里,就全部介绍结束了。

  下面给大家看一个例子,如下图:

  如图所示,我同时需要对多个工作表进行数据写入,所以我就套用了上面的模板,这样代码一目了然,而且细心的你可能会发现,为什么我的超级表会以 "表_" 开头,因为我这里直接使用的都是变量了。

  还有一个,可能你还发现我多了两个变量:StartRow 和 StartCol 。这两个是放在过程:ReadFromSQL中第27行:Range(StartRow,StartCol) 的,因为我可能同时读取了两个SQL语句,但是放在同一个超级表的不同位置。

  这些,就请大家自行发挥吧。今天的介绍就到这。希望对大家有帮助。

分享一个自己在用的从K3数据库抓取数据写入EXCEL的模板。的更多相关文章

  1. 分享一个简单的C#的通用DbHelper类(支持数据连接池)

    每次新项目的时候,都要从头去找一遍数据库工具类.这里分享一个简单实用的C#的通用DbHelper工具类,支持数据连接池. 连接池配置 <connectionStrings> <add ...

  2. 一个站点的诞生02--用Scrapy抓取数据

    假设想抓数据,就须要有爬虫程序,业内叫crawler或者spider. 有各种语言版本号的开源爬虫.c++, Java,  php,在github上搜一下,以"spider c++" ...

  3. 分享一个shell脚本的坑:grep匹配+wc取值 在脚本执行后的结果与手动执行结果不一致

    打算在跳板机上写一个shell脚本,批量检查远程服务器上的main进程是否在健康运行中. 先找出其中一台远程机器,查看main进程运行情况 [root@two002 tmp]# ps -ef|grep ...

  4. JDBC:从数据库中取数据的一个bug

    先看错误信息: java.sql.SQLException: Before start of result set at com.mysql.jdbc.SQLError.createSQLExcept ...

  5. 写一个shell脚本利用wget抓取股票历史数据

    今天,大数据部老大交给我一项任务——抓取股票历史数据.于是乎,我自行在网上找了一下,发现wget真真是一个非常强大的linux下载工具.我已经被深深震撼到了.下面叙述今天的一些过程,还是比较坎坷的. ...

  6. Jsoup抓取网页数据完成一个简易的Android新闻APP

    前言:作为一个篮球迷,每天必刷NBA新闻.用了那么多新闻APP,就想自己能不能也做个简易的新闻APP.于是便使用Jsoup抓取了虎扑NBA新闻的数据,完成了一个简易的新闻APP.虽然没什么技术含量,但 ...

  7. [apue] apue_db:一个可以充当"注册表"的 key-value 数据库

    apue 最后两章都是通过一个完整的实例来解释一些 linux 功能,第20章就是通过一个数据库实例来解释文件锁的使用, 说实话,当时没兴趣,因为满页都是源码和解析,有点看不下去.但是再拾起来硬着头皮 ...

  8. 分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)

    分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间) 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tab ...

  9. 分享一个MySQL分库分表备份脚本(原)

    分享一个MySQL分库备份脚本(原) 开发思路: 1.路径:规定备份到什么位置,把路径(先判断是否存在,不存在创建一个目录)先定义好,我的路径:/mysql/backup,每个备份用压缩提升效率,带上 ...

  10. 分享一个CQRS/ES架构中基于写文件的EventStore的设计思路

    最近打算用C#实现一个基于文件的EventStore. 什么是EventStore 关于什么是EventStore,如果还不清楚的朋友可以去了解下CQRS/Event Sourcing这种架构,我博客 ...

随机推荐

  1. 【SpringCloud】SpringCloud Stream消息驱动

    SpringCloud Stream消息驱动 消息驱动概述 是什么 什么是SpringCloudStream 官方定义Spring Cloud Stream是一个构建消息驱动微服务的框架. 应用程序通 ...

  2. Visual Studio 2017 导出 ASP.NET Core 项目模版项目文件为空

    问题重现 VS 2017 针对 ASP.NET Core 导出模版功能有问题 解决办法 visual-studio-2017-templates-and-the-missing-content 目前官 ...

  3. RegisterClass注册后getclass总是nil,why?

    这个问题有点老.但是有点烦人. 一般流程是 RegisterClass后通过getclass or findclass就会成功. 可是莫名其妙出现总是返回nil.咱也不清楚,网上找了好久,一个久远的帖 ...

  4. nodejs参数的处理与用户的交互

    解析脚本参数 作为脚本或者命令行工具,一般都需要支持不同的用户参数.默认参数被保存在process.argv的数组中,如下: [ nodeBinary, script, arg0, arg1, ... ...

  5. 等待元素加载出来后再执行下一步的方法(execute javascript指令的用法)

    上图,会员修改参数后,提示修改成功,弹出层会暂时冻结页面,导致"会员"菜单不可点击 除了使用sleep加等待时间的方法解决,本教程用"execute javascript ...

  6. jmeter使用之数据关联

  7. 把 MCP Server 打包进 VS Code extension

    大家好!我是韩老师. 本文是 MCP 系列文章的第六篇,之前的五篇是: Code Runner MCP Server,来了! 从零开始开发一个 MCP Server! 一键安装 MCP Server! ...

  8. servlet 读取表单数据

    通过post和get两种方式提交表单数据. form.html <!DOCTYPE html> <html lang="en"> <head> ...

  9. 操作系统综合题之“按要求是个进程协调完成任务,补充完整下列程序,将编号①~⑩处空缺的内容填写(Buffer缓冲区问题-代码补充)”

    1.问题:假设某系统有四个进程.input1和input2进程负责从不同设备读取数据,分别表示为data1和data2,存放在缓冲区Buffer中,output1和output2进程负责从Buffer ...

  10. Vue3 组件通信方式小结

    也是零零散散用 vue3 来搞一些前端的页面, 每次在组件通信, 主要是传数据这块总是忘记, 大多无非父传子, 子传父等情况, 这里再来做一个小结. 父传子 Props 最常见的就是父组件给子组件传递 ...