ADODB.Connection与Excel访问数据库性能改进

我们创build了一个访问数据库,一个开发者创build了一个excel的函数来访问这个数据库中的数据。 连接通过ADDB.Connection完成。 该公式返回1个数字,它是Access数据库中的一些卷的总和,并考虑了一些参数。 当我们在一个单元格中运行公式时,它的工作原理是完美的,但是由于我们的报告包含多个具有此公式的单元格(大约160个单元格)。 报告的运行速度非常慢。

我们的Access专家之一检查数据库,他没有看到它的方式有任何的错误。

有人会有一个想法如何sorting呢? 我们应该在Excel中打勾来让它工作正常吗? 我们今天在MS Excel和Access 2003上工作(我知道我们已经过时了),但我有机会升级到Excel和Access 2007(这是一个进步;-)),它会有帮助吗?

这是我们在Excel中的vba代码的细节

'The function is called GetMarketData Function GetMarketData(Optional ProductLine As String, Optional country As String, Optional CountryGroup As String, Optional Market As String, Optional startMonth As Long, Optional endMonth As Long, Optional Brand As String, Optional Model As String, Optional Segment As String, Optional EngineSegment As String) 'This is the declaration of variables Dim con As ADODB.Connection Dim rsQuery As ADODB.Recordset Dim i As Integer Dim iCount As Integer Dim resVar As Integer Dim query1 As String, query2 As String, query3 As String, query4 As String Dim parametres As String, param1 As String, param2 As String, param3 As String, param4 As String, param5 As String, param6 As String, param7 As String, param8 As String, param9 As String, param10 As String ' Query cut in 3 parts (will be regrouped later on) query1 = "SELECT Sum(T_MARKET.Volume) " query2 = "FROM T_COUNTRY_GROUP INNER JOIN (T_TIME_PERIOD INNER JOIN (T_SELECTED_MARKET INNER JOIN (T_SEGMENT INNER JOIN (T_PRODUCT_LINE INNER JOIN ((T_BRAND INNER JOIN T_MODEL ON T_BRAND.ID_Brand = T_MODEL.FK_Brand) INNER JOIN ((T_COUNTRY INNER JOIN T_MARKET ON T_COUNTRY.ID_Country = T_MARKET.FK_Country) INNER JOIN ((T_ENGINE_SEGMENT INNER JOIN T_PRODUCT ON T_ENGINE_SEGMENT.ID_Engine_Segment = T_PRODUCT.FK_Engine_Segment) " _ & "INNER JOIN T_SEGMENT_FINAL ON T_ENGINE_SEGMENT.ID_Engine_Segment = T_SEGMENT_FINAL.FK_Engine_Segment) ON (T_PRODUCT.ID_Product = T_MARKET.FK_Product) AND (T_COUNTRY.ID_Country = T_SEGMENT_FINAL.FK_Country)) ON T_MODEL.ID_Model = T_PRODUCT.FK_Model) ON T_PRODUCT_LINE.ID_Product_Line = T_SEGMENT_FINAL.FK_Product_Line) ON (T_SEGMENT.ID_Segment = T_SEGMENT_FINAL.FK_Segment) AND (T_SEGMENT.ID_Segment = T_PRODUCT.FK_Segment)) ON T_SELECTED_MARKET.ID_Selected_Market = T_SEGMENT_FINAL.FK_Selected_Market) ON T_TIME_PERIOD.ID_Period = T_MARKET.FK_Time_period) ON T_COUNTRY_GROUP.ID_Country_Groupe = T_COUNTRY.FK_Country_Group " query3 = "WHERE (" param1 = "((T_PRODUCT_LINE.Product_Line)='" & ProductLine & "')" param2 = " AND ((T_COUNTRY.Country)='" & country & "')" param3 = " AND ((T_COUNTRY_GROUP.Country_Group)='" & CountryGroup & "')" param4 = " AND ((T_SELECTED_MARKET.Selected_Market)='" & Market & "')" param5 = " AND ((T_TIME_PERIOD.Cal_FullDate)>=" & startMonth & ")" param6 = " AND ((T_TIME_PERIOD.Cal_FullDate)<=" & endMonth & ")" param7 = " AND ((T_BRAND.Brand)='" & Brand & "')" param8 = " AND ((T_MODEL.Model)='" & Model & "')" param9 = " AND ((T_SEGMENT.Segment)='" & Segment & "')" param10 = " AND ((T_ENGINE_SEGMENT.Engine_Segment)='" & EngineSegment & "')" parametres = param1 If country <> "" Then parametres = parametres & param2 End If If CountryGroup <> "" Then parametres = parametres & param3 End If If Market <> "" Then parametres = parametres & param4 End If If startMonth <> 0 Then parametres = parametres & param5 End If If endMonth <> 0 Then parametres = parametres & param6 End If If Brand <> "" Then parametres = parametres & param7 End If If Model <> "" Then parametres = parametres & param8 End If If Segment <> "" Then parametres = parametres & param9 End If If EngineSegment <> "" Then parametres = parametres & param10 End If query4 = ");" 'Connexion with the Access database Set con = New ADODB.Connection con.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" & URL_Base & ";" 'Open a recordset based on the query Set rsQuery = New ADODB.Recordset Set rsQuery.ActiveConnection = con rsQuery.Open query1 & query2 & query3 & parametres & query4 ' Give back the value from the query GetMarketData = rsQuery.Fields(0).Value 'Clear variables rsQuery.Close Set rsQuery = Nothing con.Close Set con = Nothing 

结束function

大多数情况下,DAO比使用MS Access的ADODB快得多。 这在Excel中进行了testing。 请注意, Like *不包括空值,所以这只是一个例子。 您也可以在VBA中构build临时查询并为其分配参数,但它们可能比存储的查询慢。

 Function DAOMarket(Optional ProductLine As String, Optional country As String, _ Optional CountryGroup As String, Optional Market As String, Optional startMonth As Long, _ Optional endMonth As Long, Optional Brand As String, _ Optional Model As String, Optional Segment As String, Optional EngineSegment As String) 'Reference: Microsoft Office xx Access Database Engine Object Library Dim ws As DAO.Workspace Dim db As DAO.Database Dim sDb As String Dim sSQL As String Dim qdf As QueryDef Dim rs As DAO.Recordset sDb = "Z:\Docs\Test.accdb" Set ws = DBEngine.Workspaces(0) Set db = ws.OpenDatabase(sDb) ''A stored query, see below Set qdf = db.QueryDefs("GetMarket") qdf.Parameters![@ProductLine] = IIf(ProductLine & "" = "", "*", ProductLine) qdf.Parameters![@Country] = IIf(country & "" = "", "*", country) qdf.Parameters![@Country_Group] = IIf(CountryGroup & "" = "", "*", CountryGroup) qdf.Parameters![@Selected_market] = IIf(Market & "" = "", "*", Market) qdf.Parameters![@CalStart] = IIf(startMonth & "" = "", 1, startMonth) qdf.Parameters![@CalEnd] = IIf(endMonth & "" = "", 12, endMonth) qdf.Parameters![@Brand] = IIf(Brand & "" = "", "*", Brand) qdf.Parameters![@Model] = IIf(Model & "" = "", "*", Model) qdf.Parameters![@Segment] = IIf(Segment & "" = "", "*", Segment) qdf.Parameters![@Engine_Segment] = IIf(EngineSegment & "" = "", "*", EngineSegment) Set rs = qdf.OpenRecordset(dbOpenSnapshot) DAOMarket = rs.Fields(0) End Function 

SQL

 SELECT SUM([t_market].[volume]) AS MarketVolume FROM ((t_selected_market INNER JOIN (t_product_line INNER JOIN ((t_brand INNER JOIN t_model ON t_brand.id_brand = t_model.fk_brand) INNER JOIN ((t_engine_segment INNER JOIN t_product ON t_engine_segment.id_engine_segment = t_product.fk_engine_segment) INNER JOIN t_segment_final ON t_engine_segment.id_engine_segment = t_segment_final.fk_engine_segment) ON t_model.id_model = t_product.fk_model) ON t_product_line.id_product_line = t_segment_final.fk_product_line) ON t_selected_market.id_selected_market = t_segment_final.fk_selected_market) INNER JOIN t_segment ON t_segment_final.fk_segment = t_segment.id_segment) INNER JOIN (t_country_group INNER JOIN (t_time_period INNER JOIN (t_country INNER JOIN t_market ON t_country.id_country = t_market.fk_country) ON t_time_period.id_period = t_market.fk_time_period) ON t_country_group.id_country_groupe = t_country.fk_country_group) ON t_product.id_product = t_market.fk_product WHERE ( ( ( t_product_line.product_line ) LIKE [@productline] ) AND ( ( t_country.country ) LIKE [@country] ) AND ( ( t_country_group.country_group ) LIKE [@country_group] ) AND ( ( t_selected_market.selected_market ) LIKE [@selected_market] ) AND ( ( t_time_period.cal_fulldate ) BETWEEN [@calstart] AND [@calend] ) AND ( ( t_brand.brand ) LIKE [@brand] ) AND ( ( t_model.model ) LIKE [@model] ) AND ( ( t_segment.segment ) LIKE [@segment] ) AND ( ( t_engine_segment.engine_segment ) LIKE [@engine_segment] ) );