VBA – 加速由Access发送的Excel指令

要build立一个报告,我用Access计算一些数据,然后用一个VBAmacros来导出几个表格,然后这个macros启动Excel并从Excel中运行另一个macros来编译所有的东西。

一切都已经很快了,但除了我的Access VBA之外,还需要在其中有VBA代码的Excel工作表。 所有我最近添加了很多新function到我的数据库,可以生成几个报告的选项,在Access窗体上提供了大量的定制。

在这两个文件之间导航有些复杂,所以我试图把我的Excel代码放在Access中,所以我的同事们(最终用户)只需要在他们的计算机上保存1个文件,这也会使debugging更容易。

报告按预期build成,但进程慢了5倍。 我试着测量每一步所花费的时间,并且比例保持不变(除了PowerPoint演示文稿最终build立时的部分)。

所以我决定尝试这个无用的代码:

Sub test() Dim t As Double 'Starting time t = Round(Timer) Dim b As Workbook Dim s As Worksheet Dim i As Integer, j As Integer 'Loop variables 'Create workbook Set b = Workbooks.Add 'Get worksheet Set s = b.Sheets(1) 'Double Loop For i = 1 To 100 For j = 1 To 100 s.Cells(i, j) = "Hi!" 'Write some useless comment Next Next b.Close False 'Close without saving 'Message MsgBox (Round(Timer) - t) \ 60 & "'" & Format((Round(Timer) - t) Mod 60, "00") & "''" End Sub 

我没有把ScreenUpdating = False,EnableEvents = False等作为目的。

从Excel运行代码时,需要2到3秒。

从Access运行代码时,需要7到10秒钟!

我明白,Access必须发送指令到另一个应用程序,这可能会减慢进程。 所以我试图让Excel在Excel的另一个实例中运行我的脚本(所以我创build了一个对象“Excel.Application”,其中我把我的工作簿,正是什么Access在后台),我得到了相同的性能,如果我从Access运行代码。

有什么办法可以加速吗? 改变VB脚本与其创build的应用程序对象通信的方式的指令可能是什么?

提前谢谢大家的支持。

编辑:按照ASH的要求,这里是我在Access中运行的完整代码(我不会把我的报告代码,因为它是相当大的潜艇,function,自定义类等)。 评论是法文,但这里是一个总结:

  • 第一个脚本是一个函数,用于创build或打开Excel工作簿,并进行一些优化(Excel不可见,不更新屏幕,不计算等)

  • 第二个脚本是一个closuresExcel工作簿的子工具,可以select保存/保存,并丢弃第一个函数的优化

  • 第三个脚本是我之前提供的testing代码的替代版本。

现在代码本身:

 Option Explicit Function Ouvrir_Classeur_Excel(Optional Fichier As String, Optional Optimiser As Boolean = False) As Workbook '*********************************** Descriptif 'Ouvre (ou crée) un classeur Excel en appliquant une optimisation si demandé par l'utilisateur. 'L'optimisation cache et désactive le rafraîchissement visuel d'Excel, les messages d'alerte, les événements et les calculs automatiques. '------------------ Paramètres 'Fichier : Le chemin du classeur à ouvrir. S'il est vide, un classeur est créé 'Optimiser : Indique si les scripts d'optimisation doivent être exécutés. Par défaut, cette option est désactivée '*********************************** Exécution With Excel.Application If Optimiser Then 'Excel invisible .Visible = False 'Désactivation du rafraîchissement .ScreenUpdating = False 'Désactivation des messages d'alerte .DisplayAlerts = False 'Désactivation des événements .EnableEvents = False End If 'Ouverture/Création du classeur If Fichier <> "" Then Set Ouvrir_Classeur_Excel = Workbooks.Open(Fichier) 'Si on a spécifié un fichier, il est ouvert If Fichier = "" Then Set Ouvrir_Classeur_Excel = Workbooks.Add 'Si on n'a pas spécifié de fichier, on en crée un 'Désactivation des calculs automatiques If Optimiser Then .Calculation = xlCalculationManual End With End Function Sub Fermer_Classeur_Excel(Classeur As Workbook, Optional Enregistrer As Boolean = False, _ Optional Emplacement As String, Optional Fin_Optimisation As Boolean = False) '*********************************** Descriptif 'Ferme le classeur Excel spécifié. 'Si l'utilisateur le demande, le classeur peut être enregistré, ou enregistré sous. 'Si l'utilisateur le demande, les optimisations appliquées par la fonction Ouvrir_Classeur_Excel peuvent être annulées. '------------------ Paramètres 'Classeur : Le classeur à fermer 'Enregistrer : Indique si le classeur doit être enregistré. Par défaut, cette option est désactivée 'Emplacement : Indique l'emplacement où enregistrer le classeur. Si vide, l'enregistrement sera simple. 'Fin_Optimisation : Indique si les optimisations doivent être annulées. Par défaut, cette option est désactivée '*********************************** Exécution With Excel.Application 'Enregistrement du classeur If Enregistrer Then If Emplacement = "" Then Classeur.Save If Emplacement <> "" Then Classeur.SaveAs Emplacement End If 'Réactivation des calculs automatiques If Fin_Optimisation Then .Calculation = xlCalculationAutomatic 'Fermeture du classeur Classeur.Close False If Fin_Optimisation Then 'Réactivation du rafraîchissement .ScreenUpdating = True 'Réactivation des messages d'alerte .DisplayAlerts = True 'Réactivation des événements .EnableEvents = False End If End With End Sub Sub testA() '------------Relève de l'heure de début Dim tGlo As Double 'Heure de début d'exécution du script Dim infoFin As String tGlo = Round(Timer) Dim x As Excel.Application Dim c As Workbook Dim f As Worksheet Dim i As Integer, j As Integer Set c = Ouvrir_Classeur_Excel(, True) Set f = c.Sheets(1) i = 1 Do Until i = 100 j = 1 Do Until j = 100 f.Cells(i, j) = "Coucou" j = j + 1 Loop i = i + 1 Loop Fermer_Classeur_Excel c, , , True '------------Message de fin infoFin = infoFin & Chr(10) & Chr(10) & "DUREE DE TRAITEMENT : " & (Round(Timer) - tGlo) \ 60 & "'" & Format((Round(Timer) - tGlo) Mod 60, "00") & "''" MsgBox infoFin, , title:="** FIN DU TRAITEMENT **" End Sub 

像这样,它需要2到7秒(Excel已经运行),这是相当大的优势相比,Excel中不到1。

问题是这里看起来并不重要,但是另外一个在Excel中通常需要40秒的进程,当我将其迁移到Access时花费了3分多钟。 我有另外一个(尚未优化),需要更多的3:30在Excel中,我甚至不敢尝试在Access中运行它。

我知道你提到你在Access中有很多自定义程序来产生各种报告,但是有什么理由不能把这些代码移动到Excel? 我有几个解决scheme,我已经在Excel中build立了运行代码,但使用Access作为数据源,而且它们非常快 – 您在Access中创build的用户表单必须在Excel中重新构build,但可以解决Excel之间的性能问题/访问…

希望这有助于TheSilkCode