Wrox Programmer Forums
Go Back   Wrox Programmer Forums > Microsoft Office > Excel VBA > Excel VBA
|
Excel VBA Discuss using VBA for Excel programming.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the Excel VBA section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old June 16th, 2003, 02:49 PM
Registered User
 
Join Date: Jun 2003
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Default XL2000: Query Table’s Refresh method with ADO

XL2000: Query Table’s Refresh method called with an Excel formula causes the formula to be recalled (causing Refreshing problem to the QueryTable).


SYMPTOMS:

- Our formula is recalled unexpectedly (Kind of Recursivity)
- QueryTables contaning Criterias based on Referenced Cells are not updated as Query table containing normal cells Criteria

DETAILS:

Our program use QueryTable to dynamically update data on Worksheet from an External Database.

We create QueryTable object programmatically to be updated by an ADODB Recordset for an Oracle Database.

We built our ADO Recordset Sql String from Data in a worksheet as Criteria

To dynamically update our QueryTable object with good Criteria we use a Formula that Contains a Reference to the Criteria Range.

Ex:

=ApplyFormula($D$1:$E$1 [c1],"Products_List" [c2],"AutoQryTable_1" [c3],TRUE)

When Criteria in range D1 :E1 are updated, the ApplyFormula is called automatically and Refresh Recordset for the QueryTable in parameter.

To Create the Query Table we use this function that works well:

Public Sub TransferData(p_strQryTable)
'
' Description : Create the QueryTable to transfer data from VBA to Excel with Automation
' Author : Rod Custeau
' Date : 20 Feb. 2002
' File : 1690
'
On Error GoTo TransferData_Err
Dim Rs As ADODB.Recordset
Dim oQryTable As QueryTable

    Set Rs = New ADODB.Recordset
    Rs.Open rsGR.Source, mdbLabLink, adOpenDynamic, adLockReadOnly, adCmdText

    'Create the QueryTable
    Set oQryTable = ActiveSheet.QueryTables.Add(Rs, Output_C)

    oQryTable.Name = p_strQryTable
    oQryTable.AdjustColumnWidth = False
    oQryTable.FieldNames = False
    oQryTable.EnableRefresh = True
    oQryTable.Refresh

TransferData_Exit:
On Error Resume Next
    Rs.Close
    Set Rs = Nothing
    Set oQryTable = Nothing
Exit Sub

TransferData_Err:
    MsgBox Err.Description
    GoTo TransferData_Exit
End Sub


And To Change Recordset to Refresh the QueryTable we use this function:
Note : This function is called by =ApplyFormula () when a criteria is updated

Public Sub ChangeDataFromQryTable(p_strCurrentQryTable As String)
'
' Description : Refresh the QueryTable Recordset to update Results when the
' Criterias change
' Author : Rod Custeau
' Date : 20 Feb. 2002
' File : 1690
'
' Modification : Change criteria and query is not always performed
' Author : Rod Custeau
' Date : March 19, 2002
' File : 3114
'
On Error GoTo ChangeDataFromQryTable_Err

Dim Rs As ADODB.Recordset

    Set Rs = New ADODB.Recordset
    Rs.Open rsGR.Source, mdbLabLink, adOpenDynamic, adLockReadOnly, adCmdText

    Set ActiveSheet.QueryTables(p_strCurrentQryTable).Reco rdset = Rs
    ActiveSheet.QueryTables(p_strCurrentQryTable).Refr esh[c4]

ChangeDataFromQryTable_Exit:
On Error Resume Next
    Rs.Close
    Set Rs = Nothing
Exit Sub

ChangeDataFromQryTable_Err:
    'MsgBox Err.Description
    GoTo ChangeDataFromQryTable_Exit
End Sub

I also tried to add Parameters to get rid of the = ApplyFormula() to be able to use .RefreshOnChange Method, but I was getting an Error 1004 :No value given for one parameter ….

Any Idea ?


[c1]: Criteria Range
[c2]: Oracle View
[c3]: Query table object Reference
[c4]: Using this Refresh method cause the =ApplyFormula() to be Recalled even if execution not finished yet.
 
Old April 5th, 2005, 06:17 AM
Registered User
 
Join Date: Apr 2005
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

HI,

I have the same problem in my code. Have you solved that problem or not?

Thank you.


Quote:
quote:Originally posted by Rod the mod
 XL2000: Query Table’s Refresh method called with an Excel formula causes the formula to be recalled (causing Refreshing problem to the QueryTable).


SYMPTOMS:

- Our formula is recalled unexpectedly (Kind of Recursivity)
- QueryTables contaning Criterias based on Referenced Cells are not updated as Query table containing normal cells Criteria

DETAILS:

Our program use QueryTable to dynamically update data on Worksheet from an External Database.

We create QueryTable object programmatically to be updated by an ADODB Recordset for an Oracle Database.

We built our ADO Recordset Sql String from Data in a worksheet as Criteria

To dynamically update our QueryTable object with good Criteria we use a Formula that Contains a Reference to the Criteria Range.

Ex:

=ApplyFormula($D$1:$E$1 [c1],"Products_List" [c2],"AutoQryTable_1" [c3],TRUE)

When Criteria in range D1 :E1 are updated, the ApplyFormula is called automatically and Refresh Recordset for the QueryTable in parameter.

To Create the Query Table we use this function that works well:

Public Sub TransferData(p_strQryTable)
'
' Description : Create the QueryTable to transfer data from VBA to Excel with Automation
' Author : Rod Custeau
' Date : 20 Feb. 2002
' File : 1690
'
On Error GoTo TransferData_Err
Dim Rs As ADODB.Recordset
Dim oQryTable As QueryTable

    Set Rs = New ADODB.Recordset
    Rs.Open rsGR.Source, mdbLabLink, adOpenDynamic, adLockReadOnly, adCmdText

    'Create the QueryTable
    Set oQryTable = ActiveSheet.QueryTables.Add(Rs, Output_C)

    oQryTable.Name = p_strQryTable
    oQryTable.AdjustColumnWidth = False
    oQryTable.FieldNames = False
    oQryTable.EnableRefresh = True
    oQryTable.Refresh

TransferData_Exit:
On Error Resume Next
    Rs.Close
    Set Rs = Nothing
    Set oQryTable = Nothing
Exit Sub

TransferData_Err:
    MsgBox Err.Description
    GoTo TransferData_Exit
End Sub


And To Change Recordset to Refresh the QueryTable we use this function:
Note : This function is called by =ApplyFormula () when a criteria is updated

Public Sub ChangeDataFromQryTable(p_strCurrentQryTable As String)
'
' Description : Refresh the QueryTable Recordset to update Results when the
' Criterias change
' Author : Rod Custeau
' Date : 20 Feb. 2002
' File : 1690
'
' Modification : Change criteria and query is not always performed
' Author : Rod Custeau
' Date : March 19, 2002
' File : 3114
'
On Error GoTo ChangeDataFromQryTable_Err

Dim Rs As ADODB.Recordset

    Set Rs = New ADODB.Recordset
    Rs.Open rsGR.Source, mdbLabLink, adOpenDynamic, adLockReadOnly, adCmdText

    Set ActiveSheet.QueryTables(p_strCurrentQryTable).Reco rdset = Rs
    ActiveSheet.QueryTables(p_strCurrentQryTable).Refr esh[c4]

ChangeDataFromQryTable_Exit:
On Error Resume Next
    Rs.Close
    Set Rs = Nothing
Exit Sub

ChangeDataFromQryTable_Err:
    'MsgBox Err.Description
    GoTo ChangeDataFromQryTable_Exit
End Sub

I also tried to add Parameters to get rid of the = ApplyFormula() to be able to use .RefreshOnChange Method, but I was getting an Error 1004 :No value given for one parameter ….

Any Idea ?


[c1]: Criteria Range
[c2]: Oracle View
[c3]: Query table object Reference
[c4]: Using this Refresh method cause the =ApplyFormula() to be Recalled even if execution not finished yet.
 
Old April 5th, 2005, 12:27 PM
Friend of Wrox
 
Join Date: Nov 2004
Posts: 1,621
Thanks: 1
Thanked 3 Times in 3 Posts
Default

Try blocking the actions of additional calls:
Code:
Dim InChange As Boolean

Public Sub ChangeDataFromQryTable(p_strCurrentQryTable As String)
'
' Description  : Refresh the QueryTable Recordset to update Results when the Criteria change
' Author       : Rod Custeau
' Date         : 20 Feb. 2002
' File         : 1690
'
' Modification : Change criteria and query is not always performed
' Author       : Rod Custeau
' Date         : March 19, 2002
' File         : 3114
'
    On Error GoTo Er

    Dim Rs As ADODB.Recordset

    If InChange = True then Exit Sub
    InChange = True

    Set Rs = New ADODB.Recordset
    Rs.Open rsGR.Source, mdbLabLink, adOpenDynamic, adLockReadOnly, adCmdText

    Set ActiveSheet.QueryTables(p_strCurrentQryTable).Recordset = Rs
    ActiveSheet.QueryTables(p_strCurrentQryTable).Refresh[c4]

Rs:
    On Error Resume Next
    Rs.Close
    Set Rs = Nothing
    InChange = False
    Exit Sub

Er:
    ' MsgBox Err.Description
    Resume ChangeDataFromQryTable_Exit

End Sub
The idea is to prevent additional instances of the sub from being run if it is currently running. It sounds to me as if the running of the sub changes some values that automatically call the sub when they get changed. I have trouble following your description of the problem; it is pretty terse...

But you do say that when the criteria in range D1:E1 change, ApplyFormula is automatically called. If those criteria are then changed by ApplyFormula, there would ba an additional call to ApplyFormula in response to that change.

Just a guess.
 
Old April 5th, 2005, 01:28 PM
Registered User
 
Join Date: Apr 2005
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thank you Brian,

Perhaps this code is a bit difficult to understand. I have the same trouble but will put you the code in order to understand the problem.

In a Excel Formula you put in for example:

                           =lista("select * from table1")

Lista check and prepare de SQL and fit the optional parameters and then it calls the other function "CreaConsulta".

When in CreaConsulta is reached the Refresh method, automatically is called lista function again.

And other thing I have probed the application.enableevents = false but it doesn't work.


'This is my function in Excel Formula
Public Function lista(sqlTXT As String, Optional par1 As Variant, Optional
par2 As Variant) As Variant

    Dim salida, auxSalidaOK

    'This check if the connection is opened or not. If it is closed, the
connection is created.
    If Not conexion_abierta Then
        MyConnect
    End If

    salida = ""

    'The parameters are: Par1: Destination Cell if missing is the cell under
the formula. Par2: True o False if you want headings or not.
    auxSalidaOK = CreaConsulta(sqlTXT, IIf(IsMissing(par1),
Application.Caller.Offset(1, 0), par1), IIf(IsMissing(par2), True, par2))
    salida = IIf(auxSalidaOK, "OK", "FALLO SQL")

    lista = salida
End Function



'This is the function that creates the Query
Private Function CreaConsulta(sql As String, Celda As Range, cabecera As
Boolean) As Boolean
    Dim aux As QueryTable
    Dim inter As Range
    Dim salida, nuevaConsulta As Boolean

    salida = False

    Set RS = conn.Execute(sql) 'This is a global definition

    'Look for other QueryTables in order to know if it is a new one or an
old one.
    If Celda.Worksheet.QueryTables.Count > 0 Then
        For Each aux In Celda.Worksheet.QueryTables()
            'Check the range result if intersect or not with our destination.
            Set inter = Application.Intersect(aux.Destination, Celda)

            If inter Is Nothing Then
                nuevaConsulta = True 'It is a new one
            Else
                nuevaConsulta = False 'It is a old one
                Exit For
            End If
        Next aux
    Else
        nuevaConsulta = True 'If there is no QueryTables, is a new one.
    End If

    If Not nuevaConsulta Then
        With Celda.QueryTable
            .FieldNames = IIf(cabecera, True, False)
            .RowNumbers = False
            .FillAdjacentFormulas = True
            .PreserveFormatting = True
            .BackgroundQuery = False
            .RefreshStyle = xlInsertDeleteCells
            .AdjustColumnWidth = False
            .PreserveColumnInfo = False
            Set .Recordset = RS
            salida = .Refresh(false)
            If .FetchedRowOverflow Then
                MsgBox "There is a lot of rows in the Query."
            End If
        End With
    Else
        With Celda.Worksheet.QueryTables.Add(RS, Celda)
            .FieldNames = IIf(cabecera, True, False)
            .RowNumbers = False
            .FillAdjacentFormulas = True
            .PreserveFormatting = True
            .BackgroundQuery = False
            .RefreshStyle = xlInsertDeleteCells
            .AdjustColumnWidth = False
            .PreserveColumnInfo = False
            salida = .Refresh(False)
            If .FetchedRowOverflow Then
                MsgBox "There is a lot of rows in the Query."
            End If
        End With
    End If

    CreaConsulta = salida

End Function


The function use in the Formula has to do only one thing. It has to create a
QueryTable to return all the rows and columns in the recordset.

The parameters in the function lista are:

text with the SQL
optional par1 = Destination cell where the Query Table will be inserted
optional par2 = true or false if you want headings or not in the QueryTable
And then the function lista has to return TRUE or FALSE if the QueryTable is
created ok or not. By this way you get a returned value for the formula in
Excel and get the result of the Query.

The probem is that when you get at the point .Refresh(false), insted of
continuing the running code, Excel begins to execute again lista function.

If you have only one of these formulas in you Excel, it works ok because in
the second pass, the code is runned completely. But imagine you have 3
formulas like these with diferent selects.

The running order will be:

lista (select1) -> run CreaConsulta (select1) -> When it arrives at the
point when the Refresh is called, suddenly goes to the following formula, it
is, lista (select2) and then it goes to CreaConsulta (select2) but without
finishing the code of the first formula, and by this way it goes on and on
till the last formula that is runned completely so i get only 1 result from
all i have in my worksheet.
To solve that I have to excute each formula by editing the formula and hit
Return key for each of them.

It seems to be a bug of Excel or that something is controlling some events.
But I think that functions must be finished before executing other.

have you any ideas?







Similar Threads
Thread Thread Starter Forum Replies Last Post
Using Find Method of ADO martinaccess Access 3 November 21st, 2007 07:35 AM
Automate assigning the values from one table’s tex pkaptein1 Access 1 May 14th, 2005 06:57 AM
NextRecordset method in ADO.NET? Clay ADO.NET 6 April 20th, 2005 07:54 AM
ADO DELETE METHOD JENKINSACTIVE SQL Server 2000 4 November 4th, 2004 04:58 AM
The "Meta Refresh Tag" method nancy HTML Code Clinic 5 October 28th, 2004 04:43 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.