ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 5293|回复: 19

[求助] VBA+SQL批量打印直拨单程序如何控制分页?

[复制链接]

TA的精华主题

TA的得分主题

发表于 2015-7-24 09:43 | 显示全部楼层 |阅读模式
本帖最后由 autumnalRain 于 2015-7-24 13:21 编辑

一、求助主题:想利用VBA+SQL批量打印直拨单。请各位老师依据本人思路进行指点,对本人是个学习过程。感谢……
二、本人思路:
1、生成打印清单,如【打印清单】工作表
2、以查询清单的凭证号和项目名称作为查询条件生成单个凭证号下的不同项目的领料记录,如【查询结果】工作表
3、判断领料记录是否超过10行--不超过10行,自动编号,空行不编号;超过10行刚清空以前内容,重新打印一张,并自动编号,空行不编号;见【材料直拨单模板】
三、求助内容:
第三步,如何根据查询记录行数判断是否分页,并写入数据至【材料直拨单模板】


代码如下:
Dim I As Integer
Sub 查询结果()
Dim Rmax As Integer
Dim SVoucher, SProject
Rmax = Sheets("打印清单").Range("a1").CurrentRegion.Rows.Count ' MsgBox Rmax
   
For I = 2 To Rmax
    SVoucher = Sheets("打印清单").Cells(I, 1)
    SProject = Sheets("打印清单").Cells(I, 2)
    Sheets("查询结果").Cells.Clear
    Dim cnn As Object, SQL
    Set cnn = CreateObject("ADODB.Connection")
    cnn.Open "provider=microsoft.ACE.OLEDB.12.0;extended properties='Excel 12.0;hdr=yes';data source=" & ThisWorkbook.FullName
    SQL = "select 凭证号,名称,规格,单位,数量,单价,金额,项目名称 from [项目名称$] where [凭证号]=""" & SVoucher & """ And [项目名称]= """ & SProject & """"
    Sheets("查询结果").[a1].CopyFromRecordset cnn.Execute(SQL)
     
With Sheets("材料直拨单模板") '直拨单数据写入
MsgBox I
Union(.[B2], .[C2], .[G2]).ClearContents
.[B2] = SProject
.[C2] = Right(SVoucher, Len(SVoucher) - InStrRev(SVoucher, "-"))
.[G2] = Left(SVoucher, InStrRev(SVoucher, "-")) & "28"
End With
    cnn.Close
    Set cnn = Nothing
      
   Next I
     
End Sub



批量打印程序_final.zip

96.03 KB, 下载次数: 41

TA的精华主题

TA的得分主题

发表于 2015-7-28 07:53 | 显示全部楼层
本帖最后由 opiona 于 2015-7-28 07:54 编辑

提供一个思路:

  1. <P>Set SH0 = Sheets("打印数据")
  2. Set SH1 = Sheets("打印模板")</P>
  3. <P>'//清空模板数据
  4. For IROW = 2 To SH0.Range("A65536").End(3).Row Step 10  '//10行一页
  5.     SH1.Cells(2, 2) = SH0.Cells(IROW, 2) '//模板数据在固定位置的!
  6.     For I = 1 To 10  '//一页10行
  7.         If Len(SH0.Cells(IROW + I - 1, 1)) > 0 Then '//是否空行
  8.             SH1.Cells(I, 1) = I  '//编号
  9.             SH1.Cells(I, 2) = SH0.Cells(IROW + I - 1, 1)
  10.         Else
  11.             Exit For
  12.         End If
  13.     Next</P>
  14. <P>'//打印出来
  15. Next IROW</P>
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-7-28 15:55 | 显示全部楼层
opiona 发表于 2015-7-28 07:53
提供一个思路:

老师,您能否把你的这部分代码加入到我未写完的部分?参与到FOR循环中?就是每查询一次打印一次。感谢

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-7-28 16:01 | 显示全部楼层
本帖最后由 autumnalRain 于 2015-7-29 20:55 编辑
opiona 发表于 2015-7-28 07:53
提供一个思路:

本人水平有限,只能做到这个部分,保证查询结果都是正确的。但是变化的查询结果根据其实行数判断并写入到材料直拨单模板,,如何控制分页打印确实无法解决,请帮助!
Sub 查询结果()
    Dim I As Integer
    Dim K As Integer
    Dim Rmax As Integer
    Dim SVoucher, SProject
    Dim strSQL As String
    Dim strconn As String
    Dim ADOConn As Object
   ' Dim ADORst As adodb.Recordset   ‘这句的adodb.Recordset  换成 Object执行没有问题,否则执行出现“用户定义对象未定义” 搞不清为什么 ?
Set ADOConn = CreateObject("ADODB.Connection")
    strconn = "provider=microsoft.ACE.OLEDB.12.0;extended properties='Excel 12.0;hdr=yes';data source=" & ThisWorkbook.FullName
         
    Rmax = Sheets("打印清单").Range("a1").CurrentRegion.Rows.Count
   
    For I = 2 To Rmax
        SVoucher = Sheets("打印清单").Cells(I, 1)
        SProject = Sheets("打印清单").Cells(I, 2)
        Sheets("查询结果").Cells.Clear
        
        strSQL = "select 凭证号,名称,规格,单位,数量,单价,金额,项目名称 from [项目名称$] where [凭证号]=""" & SVoucher & """ And [项目名称]= """ & SProject & """"
        ADOConn.Open strconn
        Set ADORst = ADOConn.Execute(strSQL)
        For K = 0 To ADORst.Fields.Count - 1
        Sheets("查询结果").Cells(1, K + 1) = ADORst.Fields(K).Name
        Next K
        
        Sheets("查询结果").[A2].CopyFromRecordset ADORst
   
'            With Sheets("材料直拨单模板") '直拨单数据写入
'               Union(.[B2], .[C2], .[G2]).ClearContents
'                .[B2] = SProject
'                .[C2] = Right(SVoucher, Len(SVoucher) - InStrRev(SVoucher, "-"))
'                .[G2] = Left(SVoucher, InStrRev(SVoucher, "-")) & "28"
'             End With
        ADORst.Close
        ADOConn.Close
       ' Set ADOconn = Nothing 意义何在?
    Next I
     
End Sub

批量打印程序_final.zip

95.87 KB, 下载次数: 20

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-8-1 20:35 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
CopyFromRecordset方法的使用说明


作者:bengdeng | 来源:Excel吧 | 时间:2008-10-13 | 阅读权限:游客 | 会员币:0 | 【大 中 小】






介绍CopyFromRecordset方法的目的,是因为在以后的 SQL语言教程 中,我们大部份都需要它,来完成数据库向Excel传递内容的任务,因此特别在这里列出来说明一下。下面的大部份内容,可以在Excel的VBA帮助中找到。

CopyFromRecordset 方法的功能是将一个 ADO 或 DAO Recordset 对象的内容复制到工作表中,复制的起始位置在指定区域的左上角。其语法为:

expression.CopyFromRecordset(Data, MaxRows, MaxColumns)

expression  :   必需。该表达式返回一个 Range 对象。

Data  :   Variant 类型,必需。复制到指定区域的 Recordset 对象。

MaxRows   :   Variant 类型,可选。复制到工作表的记录个数上限。如果省略该参数,将复制 Recordset 对象的所有记录。

MaxColumns  :    Variant 类型,可选。复制到工作表的字段个数上限。如果省略该参数,将复制 Recordset 对象的所有字段。

说明:复制从 Recordset 对象的当前行开始的内容。复制完成之后,Recordset 对象的 EOF 属性值为 True。

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-8-2 06:33 | 显示全部楼层

  1. Sub 查询结果()
  2.     Dim I As Integer
  3.     Dim K As Integer
  4.     Dim Rmax As Integer
  5.     Dim SVoucher, SProject
  6.     Dim SQL As String
  7.     Dim conn As String
  8.     Dim ADOConn As Object
  9.     Dim ADORst As Object
  10.    
  11.     Set ADOConn = CreateObject("ADODB.Connection")
  12.     Set ADORst = CreateObject("ADODB.Recordset")
  13.     conn = "provider=microsoft.ACE.OLEDB.12.0;extended properties='Excel 12.0;hdr=yes';data source=" & ThisWorkbook.FullName
  14.          
  15.     Rmax = Sheets("打印清单").Range("a1").CurrentRegion.Rows.Count
  16.    
  17.     For I = 2 To Rmax
  18.         SVoucher = Sheets("打印清单").Cells(I, 1)
  19.         SProject = Sheets("打印清单").Cells(I, 2)
  20.         Sheets("查询结果").Cells.Clear
  21.         
  22.         SQL = "select 凭证号,名称,规格,单位,数量,单价,金额,项目名称 from [项目名称$] where [凭证号]=""" & SVoucher & """ And [项目名称]= """ & SProject & """"
  23.         ADOConn.Open conn
  24.         ADORst.Open SQL, ADOConn, 3, 3
  25.         
  26.         Debug.Print ADORst.RecordCount '得到记录集的行数
  27.         For K = 0 To ADORst.Fields.Count - 1
  28.         Sheets("查询结果").Cells(1, K + 1) = ADORst.Fields(K).Name
  29.         Next K
  30.         
  31.         Sheets("查询结果").[A2].CopyFromRecordset ADORst
  32.    
  33. '            With Sheets("材料直拨单模板") '直拨单数据写入
  34. '               Union(.[B2], .[C2], .[G2]).ClearContents
  35. '                .[B2] = SProject
  36. '                .[C2] = Right(SVoucher, Len(SVoucher) - InStrRev(SVoucher, "-"))
  37. '                .[G2] = Left(SVoucher, InStrRev(SVoucher, "-")) & "28"
  38. '             End With
  39.         ADORst.Close
  40.         ADOConn.Close
  41.        'Set ADORst = Nothing
  42.        'Set ADOConn = Nothing
  43.     Next I
  44.      
  45. End Sub

复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-10-26 14:28 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 autumnalRain 于 2015-10-27 10:59 编辑

在朱荣兴老师的指导下,得以解决!感谢!
  1. Sub 批量打印()
  2. Set ADOConn = CreateObject("ADODB.Connection")
  3. Set ADORst = CreateObject("ADODB.Recordset")
  4. conn = "provider=microsoft.ACE.OLEDB.12.0;extended properties='Excel 12.0;hdr=yes';data source=" & ThisWorkbook.FullName
  5. Rmax = Sheets("查询清单").Range("a1").CurrentRegion.Rows.Count
  6. For i = 2 To Rmax
  7.     SVoucher = Sheets("查询清单").Cells(i, 1)
  8.     SProject = Sheets("查询清单").Cells(i, 2)
  9.     Sheets("查询结果").Cells.Clear
  10.     SQL = "select 名称,规格,单位,数量,单价,金额 from [项目名称$] where [凭证号]=""" & SVoucher & """ And [项目名称]= """ & SProject & """" '注意在VBA中SQL使用where多条件查询时的表达方法
  11.     ADOConn.Open conn
  12.     ADORst.Open SQL, ADOConn, 3, 3
  13.     Debug.Print ADORst.RecordCount
  14.     For k = 0 To ADORst.Fields.Count - 1
  15.         Sheets("查询结果").Cells(1, k + 1) = ADORst.Fields(k).name
  16.     Next k
  17.     Sheets("查询结果").[a2].CopyFromRecordset ADORst

  18.     With Sheets("打印模板")
  19.     Union(.[B2], .[C2], .[G2]).ClearContents
  20.     .[B2] = SProject
  21.     .[e2] = Right(SVoucher, Len(SVoucher) - InStrRev(SVoucher, "-"))
  22.     .[G2] = Left(SVoucher, InStrRev(SVoucher, "-")) & "28"
  23. '      For X = 2 To Sheets("查询结果").Cells(Rows.Count, 1).End(xlUp).Row Step 10
  24.       For X = 2 To ADORst.RecordCount + 1 Step 10
  25.        Sheets("打印模板").Range("b4:g13").ClearContents
  26.        Sheets("查询结果").Range("A" & X & ":F" & X + 9).Copy
  27.        Sheets("打印模板").Cells(4, 2).PasteSpecial Paste:=xlPasteValues
  28.        ActiveSheet.PrintOut From:=1, To:=1, Copies:=1
  29.       Next
  30.      End With
  31.     ADORst.Close
  32.     ADOConn.Close
  33. Next i
  34. Set ADORst = Nothing
  35. Set ADOConn = Nothing
  36. End Sub
复制代码




补充内容 (2016-2-15 19:50):
本方法可以简化,[查询结果$]表可以省略,如何取依次取每个10条记录,见9楼赵老师的代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-10-26 14:29 | 显示全部楼层
本帖最后由 autumnalRain 于 2015-11-3 08:38 编辑

特别感谢朱荣兴老师!一直以来都犯了个低级错误。原来我的理解一直都是错误的:象本例循环几次,打印几次,每次循环打印的内容也发生了变化。我却理解成只打印了最后一次。恍然大悟!

批量打印.rar

37.11 KB, 下载次数: 108

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-2-15 19:47 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
学习贴:要求将查询结果按照每35行分一次列,写到[个人捐款汇总$]中,查询条件为活动工作表的科目[F1]日期介于[B2]和[D2]间
赵刚老师的代码解决了一直以来的疑惑,在此转到本贴,当做学习笔记!
应该重点学习的内容是依次取得第一个35条记录,第二个35条记录……第N个35条记录,如何写代码见代码第8-11行
  1. Sub ADO法()
  2.     Dim cnn As Object, rs As Object, SQL$, i&
  3.     Set cnn = CreateObject("ADODB.Connection")
  4.     cnn.Open "Provider = Microsoft.Jet.Oledb.4.0;Extended Properties ='Excel 8.0;hdr=no';Data Source =" & ThisWorkbook.FullName
  5.     SQL = "Select f1,f3,f6,f7 from [收支记录$a4:g]  where f2='" & [f1] & "' and f1 between #" & [b2] & "# and #" & [d2] & "#"
  6.     Set rs = cnn.Execute(SQL)
  7.     [a1].CurrentRegion.Offset(3).ClearContents
  8.     While Not rs.EOF
  9.          Cells(4, i + 1).CopyFromRecordset rs, 35
  10.          i = i + 4
  11.     Wend
  12.     rs.Close
  13.     cnn.Close
  14.     Set rs = Nothing
  15.     Set cnn = Nothing
  16. End Sub
复制代码

把查询结果每35行分一次列.rar

76.83 KB, 下载次数: 29

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-2-15 20:32 | 显示全部楼层
特别需要强调的一句话:
使用CopyFromRecordset方法时,复制从 Recordset 对象的当前行开始的内容。复制完成之后,Recordset 对象的 EOF 属性值为 True
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-5 03:23 , Processed in 0.048907 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表