找回密码
 加入
搜索
查看: 199|回复: 2

[AU3基础] AU3读写打印Excel表格,被占用、数组行列反向、效率问题

[复制链接]
发表于 2026-4-2 13:21:31 | 显示全部楼层 |阅读模式
原以为AU3只能通过Excel.UDF读写Excel表格,看UDF时发现调用的是Excel.Application,想着学习一下EXCEL操作就随手做了个EXCEL表格,用AI拼了以下代码,现在有以下几个问题:

1.Excel文档被其它编辑器打开(占用)时如何处理
2.读取单元格区域到数组,行列与单元格区域相反,当表格数据量大(比如一万行或百万行)时数组列是否够用
3.日期读取到数组再写回时转换异常
4.写法、逻辑、效率方面是否有问题
#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <DateTimeConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <date.au3>
#Region ### START Koda GUI section ### Form=
Global $oExcel
Global $SaleLists[1][5]
Global $CustomerInfo[1][2]
Global $Prices[1][2]
Global $CheckLists[1][6]
$Form1 = GUICreate("表格操作学习", 623, 449, 232, 113)
$Group1 = GUICtrlCreateGroup("基础设置", 8, 8, 521, 121)
$Label1 = GUICtrlCreateLabel("接口:", 28, 33, 31, 17)
$Radio1excel = GUICtrlCreateRadio("微软Excel", 83, 29, 89, 25)
$Radio2wpssheet = GUICtrlCreateRadio("金山WPS表格", 186, 29, 113, 25)
$Label11 = GUICtrlCreateLabel("", 450, 33, 75, 24) ;接口连接状态
$Label2 = GUICtrlCreateLabel("工作簿:", 28, 70, 43, 17)
$iWorkBookInput = GUICtrlCreateInput("请选择或输入文档路径", 83, 64, 361, 21)
GUICtrlSetState(-1, $GUI_DISABLE)
$Button1 = GUICtrlCreateButton("浏览", 450, 64, 65, 25)
GUICtrlSetState(-1, $GUI_DISABLE)
$Label3 = GUICtrlCreateLabel("打印机:", 28, 95, 43, 17)
$Button2 = GUICtrlCreateButton("属性", 450, 96, 65, 25)
$iPrinterInput = GUICtrlCreateCombo("", 83, 96, 361, 25, BitOR($CBS_DROPDOWNlist, $CBS_AUTOHSCROLL))
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Group2 = GUICtrlCreateGroup("数据调用", 8, 144, 521, 137)
$Label5 = GUICtrlCreateLabel("起止日期:", 24, 176, 64, 17)
$iDateStartInput = GUICtrlCreateDate("", 108, 168, 105, 25)
$iDateEndInput = GUICtrlCreateDate("", 258, 168, 121, 25)
$Label6 = GUICtrlCreateLabel("-->", 228, 176, 22, 17)
$Label7 = GUICtrlCreateLabel("客户名称:", 24, 208, 64, 17)
$CustomerInput = GUICtrlCreateCombo("待读取", 108, 208, 105, 25, BitOR($CBS_DROPDOWNlist, $CBS_AUTOHSCROLL))
$Label8 = GUICtrlCreateLabel("打印工作表:", 23, 248, 76, 17)
$iSheetInput = GUICtrlCreateCombo("待读取", 108, 240, 105, 25, BitOR($CBS_DROPDOWNlist, $CBS_AUTOHSCROLL))
$Label9 = GUICtrlCreateLabel("复本数:", 223, 248, 76, 17)
$iCopyInput = GUICtrlCreateCombo("", 278, 240, 105, 25, BitOR($CBS_DROPDOWNlist, $CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "1|2|3|4|5", 1)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Button3 = GUICtrlCreateButton("读取数据", 100, 312, 100, 25)
$Button4 = GUICtrlCreateButton("读取数据并打印", 260, 312, 161, 25)
GUICtrlSetState(-1, $GUI_DISABLE)

Local $oWMIService = ObjGet("winmgmts:\\.\root\cimv2")
If Not IsObj($oWMIService) Then
        MsgBox(16, "错误", "无法连接 WMI 服务")
        Exit
EndIf

Local $oPrinters = $oWMIService.ExecQuery("SELECT * FROM Win32_Printer")
If Not IsObj($oWMIService) Then
        MsgBox(16, "错误", "无法连接 WMI 服务")
        Exit
EndIf

For $oPrinter In $oPrinters
If $oPrinter.Default = True Then
                GUICtrlSetData($iPrinterInput, $oPrinter.Name, $oPrinter.Name)
        Else
                GUICtrlSetData($iPrinterInput, $oPrinter.Name)
        EndIf
Next
;_ArrayDisplay($aList, "WMI 获取的已安装打印机")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit
                Case $Radio1excel
                        GUICtrlSetData($iWorkBookInput, '请选择或输入文档路径')
                        GUICtrlSetState($Button3, $GUI_DISABLE)
                        GUICtrlSetState($Button4, $GUI_DISABLE)
                        GUICtrlSetData($Label11, '[连接中...]')
                        GUICtrlSetColor($Label11, 0x00ff00)
                        Local $oExcel = ObjCreate("Excel.Application") ; 创建 Excel 对象
                        If Not IsObj($oExcel) Then
                                GUICtrlSetData($Label11, '[连接失败]')
                                GUICtrlSetColor($Label11, 0xff0000)
                                GUICtrlSetState($iWorkBookInput, $GUI_DISABLE)
                                GUICtrlSetState($Button1, $GUI_DISABLE)
                                ;GUICtrlSetState($Button3, $GUI_DISABLE)
                        Else
GUICtrlSetData($Label11, '[连接成功]')
                                GUICtrlSetColor($Label11, 0x0000FF)
                                GUICtrlSetState($iWorkBookInput, $GUI_ENABLE)
                                GUICtrlSetState($Button1, $GUI_ENABLE)
                                ;GUICtrlSetState($Button3, $GUI_ENABLE)
EndIf

                Case $Radio2wpssheet
                        GUICtrlSetData($iWorkBookInput, '请选择或输入文档路径')
                        GUICtrlSetState($Button3, $GUI_DISABLE)
                        GUICtrlSetState($Button4, $GUI_DISABLE)
                        GUICtrlSetData($Label11, '[连接中...]')
                        GUICtrlSetColor($Label11, 0x00ff00)
                        Local $oExcel = ObjCreate("ET.Application") ; 创建 Excel 对象
                        If Not IsObj($oExcel) Then
                                GUICtrlSetData($Label11, '[连接失败]')
                                GUICtrlSetColor($Label11, 0xff0000)
                                GUICtrlSetState($iWorkBookInput, $GUI_DISABLE)
                                GUICtrlSetState($Button1, $GUI_DISABLE)
                                ;GUICtrlSetState($Button3, $GUI_DISABLE)
                        Else
GUICtrlSetData($Label11, '[连接成功]')
                                GUICtrlSetColor($Label11, 0x0000FF)
                                GUICtrlSetState($iWorkBookInput, $GUI_ENABLE)
                                GUICtrlSetState($Button1, $GUI_ENABLE)
                                ;GUICtrlSetState($Button3, $GUI_ENABLE)
EndIf
                Case $Button1 ;浏览按钮
                        $ChooseFile = FileOpenDialog('请选择工作簿', @DesktopDir & '\', '工作簿(*.xls;*.xlsx;*.et;*.ett)', 1)
                        If @error Then
                                GUICtrlSetData($iWorkBookInput, '请选择或输入文档路径')
                                GUICtrlSetState($Button3, $GUI_DISABLE)
                                GUICtrlSetState($Button4, $GUI_DISABLE)
                                MsgBox(16 + 8192, "提示:", "你没有选择文件!")
Else
$msg2 = MsgBox(1 + 48 + 8192, '警告:', '本程序将接管以下文档,请确定该文档已关闭:' & @CRLF & @CRLF & $ChooseFile & @CRLF & @CRLF & '注:受环境影响,此操作可能耗时较长')
                                If $msg2 = 1 Then
                                        GUICtrlSetData($iWorkBookInput, $ChooseFile)
                                        $oWorkBook = $oExcel.WorkBooks.Open(GUICtrlRead($iWorkBookInput)) ;当文档未关闭时如何处理:被Excel和WPS或其它程序占用时是否不同
                                        $oExcel.Visible = True ;autoit 3.3.7.15不生效
                                        $CustomerRows = $oWorkBook.Sheets('客户信息').Cells($oWorkBook.Sheets('客户信息').Rows.Count, 1).End(-4162).Row
ReDim $CustomerInfo[2][$CustomerRows - 1] ;有BUG,写入数组行列相反
                                        $CustomerInfo = $oWorkBook.Sheets('客户信息').cells(2, 1).resize($CustomerRows - 1, 2).value
                                        _ArrayTranspose($CustomerInfo) ;行列转置
GUICtrlSetData($CustomerInput, '')
                                        GUICtrlSetData($CustomerInput, '请选择客户', '请选择客户')
For $iCustRow = 0 To UBound($CustomerInfo, 1) - 1
                                                GUICtrlSetData($CustomerInput, $CustomerInfo[$iCustRow][0])
Next
                                        GUICtrlSetData($iSheetInput, '')
                                        GUICtrlSetData($iSheetInput, '请选择工作表', '请选择工作表')
                                        For $iSheetNums = 1 To $oWorkBook.Worksheets.Count
                                                GUICtrlSetData($iSheetInput, $oWorkBook.Worksheets($iSheetNums).Name) ;工作表写入
Next
GUICtrlSetState($Button3, $GUI_ENABLE)
                                        GUICtrlSetState($Button4, $GUI_ENABLE) ;解锁打印按钮
                                Else
                                        GUICtrlSetData($iWorkBookInput, '请选择或输入文档路径')
                                        GUICtrlSetState($Button3, $GUI_DISABLE)
                                        GUICtrlSetState($Button4, $GUI_DISABLE)

                                EndIf
                        EndIf
                Case $Button2 ;打印机属性按钮
ShellExecute("rundll32.exe", 'printui.dll,PrintUIEntry /p /n "' & GUICtrlRead($iPrinterInput) & '"')
                Case $Button3 ;读取按钮
                        _ReadData()
                Case $Button4 ;读取并打印按钮
                        _ReadData()
$oWorkBook.Sheets(GUICtrlRead($iSheetInput)).PrintOut(Default, _     ; From
    Default, _     ; To
    GUICtrlRead($iCopyInput), _    ; Copies复本份数
    False, _       ; Preview = False(不显示预览)
    GUICtrlRead($iPrinterInput), _   ; ActivePrinter打印机
        False, _            ; PrintToFile = False 保存到文件
    True)          ; Collate = True(逐份打印)
        EndSwitch
WEnd

Func _ReadData()
        $SaleListRows = $oWorkBook.Sheets('销售记录').Cells($oWorkBook.Sheets('销售记录').Rows.Count, 1).End(-4162).Row
        ReDim $SaleLists[5][$SaleListRows - 1]      ;行列相反
        $SaleLists = $oWorkBook.Sheets('销售记录').cells(2, 1).resize($SaleListRows - 1, 5).value
        _ArrayTranspose($SaleLists)
$PricesRows = $oWorkBook.Sheets('商品信息').Cells($oWorkBook.Sheets('商品信息').Rows.Count, 1).End(-4162).Row
        ReDim $Prices[5][$SaleListRows - 1]      ;行列相反
        $Prices = $oWorkBook.Sheets('商品信息').cells(2, 1).resize($PricesRows - 1, 2).value
        _ArrayTranspose($Prices)
        $iCheckListRow = 0
        $Total = 0
        For $iSaleListNum = 0 To UBound($SaleLists, 1) - 1
                $iDateStart = _DateDiff("d", "1899/12/30", GUICtrlRead($iDateStartInput))
                $iDateEnd = _DateDiff("d", "1899/12/30", GUICtrlRead($iDateEndInput))
                If $SaleLists[$iSaleListNum][0] >= $iDateStart And $SaleLists[$iSaleListNum][0] <= $iDateEnd and $SaleLists[$iSaleListNum][1]=GUICtrlRead($CustomerInput) Then;日期和客户名都对应时
                        $oWorkBook.Sheets('对账单').range("E2").value=GUICtrlRead($iDateStartInput) & '至' & GUICtrlRead($iDateEndInput)
$oWorkBook.Sheets('对账单').range("B2").value=GUICtrlRead($CustomerInput)
ReDim $CheckLists[$iCheckListRow+1][6]
$CheckLists[$iCheckListRow][0] = _DateAdd("D", $SaleLists[$iSaleListNum][0], "1899-12-30") ;对账单第1列=销售记录第1列,格式不对
                        $CheckLists[$iCheckListRow][1] = $SaleLists[$iSaleListNum][2] ;对账单第2列=销售记录第3列
                        $CheckLists[$iCheckListRow][2] = $SaleLists[$iSaleListNum][3] ;对账单第3列=销售记录第4列

For $DiscountNum = 0 To UBound($CustomerInfo, 1) - 1
                                If $SaleLists[$iSaleListNum][1] = $CustomerInfo[$DiscountNum][0] Then
                                        $Discount = $CustomerInfo[$DiscountNum][1] ;折扣
                                EndIf
                        Next ;$DiscountNum
                        For $PricesNum = 0 To UBound($Prices, 1) - 1
                                If $SaleLists[$iSaleListNum][2] = $Prices[$PricesNum][0] Then
                                        $CheckLists[$iCheckListRow][3] = Round($Prices[$PricesNum][1] * $Discount / 100, 1) ;对账单第4列单价
                                EndIf
                        Next ;$PricesNum
                                                $CheckLists[$iCheckListRow][4] = $CheckLists[$iCheckListRow][2] * $CheckLists[$iCheckListRow][3] ;对账单第5列=销售记录第3列*4列
                        $CheckLists[$iCheckListRow][5] = $SaleLists[$iSaleListNum][4] ;对账单第6列=销售记录第5列
                        $Total += $CheckLists[$iCheckListRow][4] ;总价
                                                                $iCheckListRow += 1
                                        EndIf
        Next ;$iSaleListNum
_ArrayTranspose($CheckLists)
        $oWorkBook.Sheets('对账单').cells(4, 1).resize(UBound($CheckLists, 2) , 6).value = $CheckLists
        $oWorkBook.Sheets('对账单').cells(4+UBound($CheckLists, 2) , 1).value ='合计:'
        $oWorkBook.Sheets('对账单').cells(4+UBound($CheckLists, 2) , 5).value =        $Total
EndFunc   ;==>_ReadData
附表格样式:








表格:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2026-4-14 16:02:48 | 显示全部楼层
autoit操控excel是很普遍的应用,期待大神进一步优化,感谢楼主分享!
发表于 7 天前 | 显示全部楼层
读取单元格区域到数组,行列与单元格区域相反

我常用来读取学生成绩,如果行列按直接读取的显示,会显示的比较慢,行列转化后还是比较快,另外当行比较多(不用几万,有1千左右)用
$a_Arr = .parent.application.transpose($a_Arr)的方法转化行列会读取失败
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2026-4-25 20:21 , Processed in 0.069611 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2026 Discuz! Team.

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