BusinessObjects Board

How to loop the cells of a report via VBA script ?

I am trying to read the variables of Report tables through a VBA script, so that I can use those values in the script, instead of reading a XLS spreadsheet or anything else.

This is my code :

Sub main()

Dim doc As Document
Dim vars As DocumentVariables
Dim var As DocumentVariable
Dim Tmp As Variant
Dim nbValues As Long
Dim ColumnIndex As Variant
Dim rowIndex As Long
Dim GetCellValue As Variant

Set doc = Application.ActiveDocument
Set vars = doc.DocumentVariables

Dim strMsg As String
Dim NbRecords As Integer

For i = 1 To vars.Count

Set var = vars.Item(i)    ' Column Index
Tmp = var.Values(BoAllValues)

For j = 1 To UBound(var.Values(BoAllValues))

GetCellValue = CStr(Tmp(j)) ' Row Index

' NbRecords = UBound(var.Values(BoAllValues))
' MsgBox (NbRecords)

strMsg = strMsg & "Col:" & i & "- Row:" & j & " = " & GetCellValue & "|"

Next j
Next i

MsgBox strMsg

End Sub

This is what I am getting :

It seems that there is no structure order as my report looks like :

I know that there is probably another more structured way of accessing the report with the tables, cells etc …

I can forward my small report again if it does help of course.

Cheers

Pascal[/quote]


eVolition :australia: (BOB member since 2002-09-01)

[/quote]

Hi Pascal,

I am trying to execute your code but am getting

RunTime eroor
Type mismatch (Error 13)

for the line
Tmp = var.Values(BoAllValues)

I have a small doubt here…Is GetCellValue = CStr(Tmp(j)) reading the cell values of each tab or variable values of the data providers?

Thanks for the code…


Ravi Amara :us: (BOB member since 2002-10-02)

I finally rework in depth the script as the initial one was not workable.
As as soon as I modified a field on the report, the col & row identifiers were changing all the time so not manageable.

I will publish the final production version of that script in a few days.

Cheers

Pascal

( PS : I double check (cut & past it in BusObj VBA window) the script publish and it does work fine for me) I am using the Module


eVolition :australia: (BOB member since 2002-09-01)

Here is the new code using a slightly different approach which is more reliable.

This piece of code is reading the report attached to the script, in order to get the parameters, so that a user can type his parameters directly in the report’s cells instead of using some database and/or Excel spreadsheet.

Then it is looping through the list of reports, looping based on one SQL order in order to refresh them for some different values, and publish a copy of the refreshed report back in the Corporate Document list.

I guess the loop to get the list of cell starts at “For Each objRep In objDoc.Reports” and ends up pretty much at “Initialising Parameters From the Report”.

But I thought you would be interested in the whole report.
I can’t copy the report itself not even a screen copy so it may be difficult to have it, but if you are interested, just drop me an email.

This script combines, Reading the Report Structure, running some SQL through ODBC as well as publishing back to the repository.

The following piece of code needs to be Cut & Paste in the VBA windows under the Module area, well that is the way I used to do it :wink:
( Don’t tell me it is not working as we use that script in Production now and works like a charm ;-), we are using BusinessObjects 5.1.5 )

Option Explicit

'Database & Repository Constants
Public objCon As ADODB.Connection

Sub Main()

Dim objDoc As busobj.Document
Dim objStruct As busobj.SectionStructure
Dim objStructItem As busobj.ReportStructureItem
Dim objBlock As busobj.BlockStructure
Dim objPivot As busobj.Pivot
Dim objDocVar As busobj.DocumentVariable

Dim vars As DocumentVariables
Dim var As DocumentVariable

Dim objRS As ADODB.Recordset
Dim objRep As busobj.Report

Dim strDocDir As String
Dim strPromptValue As String
Dim strAlternativeField As String
   
Dim doc As Document
Dim ObjectCounter As Integer
   
Dim strMsg As String
   
Dim CONNECTION_STR As String
Dim EXCH_DOMAIN As String

' Report Constants
Dim DOC_NAME As String
Dim REPORT_PROMPT As String
Dim DOC_CATEGORY As String
Dim USER_GROUP As String

' Prompt Constants
Dim SQL_STRING As String
Dim PROMPT_VALUE As String

Dim CalendarMonth As String
Dim FinancialYear As String

    ' Set to the previous calendar Month
    If Month(Now()) = 1 Then
        CalendarMonth = Str(12)
    Else
        CalendarMonth = Str(Month(Now()) - 1)
    End If
    
    ' Set the Financial Year
    If Val(CalendarMonth) >= 10 Then
        FinancialYear = Str(Year(Now()) + 1)
    Else:
        FinancialYear = Str(Year(Now()))
    End If    

' ----------START FOR CELL LOOP ------

    Set doc = Application.ActiveDocument
    Set vars = doc.DocumentVariables

    Set objDoc = Application.ActiveDocument
    For Each objRep In objDoc.Reports
        Set objStruct = objRep.GeneralSectionStructure
        ObjectCounter = 1
                
        For Each objStructItem In objStruct.Body
                Select Case objStructItem.Type
                    Case boCell
                            Select Case ObjectCounter
                                Case 2
                                    DOC_NAME = objStructItem.Variable.Formula
                                Case 6
                                    REPORT_PROMPT = objStructItem.Variable.Formula
                                Case 7
                                    DOC_CATEGORY = objStructItem.Variable.Formula
                                Case 10
                                    SQL_STRING = objStructItem.Variable.Formula
                                Case 11
                                    CONNECTION_STR = objStructItem.Variable.Formula
                                Case 14
                                    EXCH_DOMAIN = objStructItem.Variable.Formula
                                Case 16
                                    PROMPT_VALUE = objStructItem.Variable.Formula
                                Case 18
                                    USER_GROUP = objStructItem.Variable.Formula
                            End Select
                End Select
                ObjectCounter = ObjectCounter + 1
        Next
    Next

    ' Initialising Parameters From the Report
    
    'MsgBox CONNECTION_STR
    'MsgBox EXCH_DOMAIN
    'MsgBox DOC_NAME
    'MsgBox REPORT_PROMPT
    'MsgBox DOC_CATEGORY
    'MsgBox SQL_STRING
    'MsgBox PROMPT_VALUE
    'MsgBox USER_GROUP

' ----------END FOR CELL LOOP ------           

    Dim ReportName As String
    Dim WorkingReport As String
    Dim StrStart As Integer
    Dim StrEnd As Integer
    
    
    strDocDir = Application.GetInstallDirectory(boDocumentDirectory)
    
    If Dir(strDocDir, vbDirectory) = "" Then
        Err.Raise 63000
    End If
    
    ' Setting up the Repository Access
    Application.ExchangeMode = boRepositoryMode
    Application.ExchangeDomain = EXCH_DOMAIN
        
    ' Looping through a list of Reports
    WorkingReport = DOC_NAME
    If Right(WorkingReport, 1) <> ";" Then WorkingReport = WorkingReport + ";"
        
    While Len(WorkingReport) > 0
        StrEnd = InStr(1, WorkingReport, ";", 1)
        ReportName = Mid(WorkingReport, 1, StrEnd - 1)
        'MsgBox ReportName
        
        WorkingReport = Mid(WorkingReport, StrEnd + 1, Len(WorkingReport) - StrEnd + 1)
    
        ' Retrieving the Document from the Repository (Document Domain specified in EXCH_DOMAIN)
        Application.Documents.Receive ReportName, strDocDir
        Set objDoc = Application.Documents.Open(ReportName &amp; ".rep")
    
        ' Setting ODBC connection
        Set objCon = New Connection
        objCon.Open CONNECTION_STR
        If Err.Number <> 0 Then
           Err.Raise 63001
        End If
                
        Set objRS = New ADODB.Recordset
        objRS.Open SQL_STRING, objCon, adOpenKeyset, adLockOptimistic
        If Err.Number <> 0 Then
            Err.Raise 63002
        End If
       
        While Not objRS.EOF
            ' Setting the
            strPromptValue = objRS.Fields(PROMPT_VALUE)
            strAlternativeField = Trim(objRS.Fields("AlternativeField"))
            
            ' Setting the value of the prompt based on the selected value in the SQL
            Application.Variables.Item(REPORT_PROMPT).Value = strPromptValue
        
            ' Setting the Refreshing Mode to Batch
            Application.Variables.Item("Select Refresh Mode (Batch Refresh = B/ User Refresh = U)").Value = "B"
            Application.Variables.Item("Select Calendar Month").Value = Trim(CalendarMonth)
            Application.Variables.Item("Select Financial Year").Value = Trim(FinancialYear)
        
            ' Refreshing the report
            Application.Interactive = False
            Application.Documents(ReportName).Refresh
        
            ' Replacing the "/" by an hyphen "-"
            If InStr(1, strPromptValue, "/", 1) <> 0 Then
                Mid(strPromptValue, InStr(1, strPromptValue, "/", 1), 1) = "-"
            End If
            
            ' Changing the name of the report to reflect the level (Entity / Project)
            Application.Documents(ReportName).SaveAs strDocDir &amp; "\" &amp; ReportName &amp; "_" &amp; strPromptValue &amp; ".rep"
        
            ' Publishing the report to the repository in the right category
            Application.Interactive = False
            If strAlternativeField <> "" Then
                Application.Documents(ReportName &amp; "_" &amp; strPromptValue).Send USER_GROUP, , , strAlternativeField &amp; " " &amp; DOC_CATEGORY, , EXCH_DOMAIN
            Else
                Application.Documents(ReportName &amp; "_" &amp; strPromptValue).Send USER_GROUP, , , strPromptValue &amp; " " &amp; DOC_CATEGORY, , EXCH_DOMAIN
            End If
            
            Application.Interactive = True
        
            ' Changing back the name of the report
             Application.Documents(ReportName &amp; "_" &amp; strPromptValue).SaveAs strDocDir &amp; "\" &amp; ReportName &amp; ".rep"
        
            objRS.MoveNext
        
        Wend
    
        If objRS.State = 1 Then 'recordset is opened
            objRS.Close
        End If

        If objCon.State = 1 Then    'connection is opened
            objCon.Close
        End If
        Set objRS = Nothing
        Set objCon = Nothing
    
    Wend
        
    'Application.Interactive = True
Exit Sub

End Sub

eVolition :australia: (BOB member since 2002-09-01)

WOW…Thanks for the code pascal…
I got plenty of work to do during the weekend then:) The code looks intimidating :frowning:

Definitely, I would like to have a look at the whole report but my main interest is in the “looping thru the cells” part. Let me play around a little bit and hopefully will come back with couple of questions.

By the way, For the line:
Public objCon As ADODB.Connection

I am getting
compile error:
user-defined type not defined

Do I need any ODBC connection to run this macro? Can you please give more details about your environment? And, if possible, more comments?

Thanks a lot.


Ravi Amara :us: (BOB member since 2002-10-02)

Here’s some discussion on connecting to databases…

The ADO information has been really helpful to me!


Eileen King :us: (BOB member since 2002-07-10)

If your first interest is looping the cells then forget about the ADODB stuff.
It is another loop.

So the only part you are interested in is the one between the 2 tags ’ — START & '— END

Yes you will need an ODBC connection for that.

I should work on a more generic version on the efashion universe, but I am really flat out at the moment, sorry guys.

Pascal

PS : Would it be anyway I can make that report available to you ?


eVolition :australia: (BOB member since 2002-09-01)

Glad it is directly useful to somebody :wink:

Cheers

Pascal


eVolition :australia: (BOB member since 2002-09-01)

Pascal,

I’ve set up a Yahoo!Group where you can post files…then you could post a link back here to that attachment…

I know that digpen has one also…

If you send the code to “Bob” he’ll be able to post it on the code samples.

All I know is that I’ve learned more in the last three weeks than I imagined possible! Between you, Rosalind, and my new best friend Avaski…I’m in heaven!

I purchased a book on VB and ADO the other day. I still haven’t decided if it’s a good one or not.

The only thing I have left to figure out is how to get my output parameter from a stored procedure…I can see it! I just haven’t figured out the exact syntax yet…You have all helped me to do things I didn’t believe I couldn’t do…but it took me a year to get there!!!


Eileen King :us: (BOB member since 2002-07-10)

Sorry for my ignorance Pascal. But, How it is looping thru the report?

  1. Are you taking each data provider and retrieving the values of each row in the Data Provider?
    OR
  2. Is it something like going to each tab page and fetch the values of the cells?

I am very much interested in the second option… But, I heard that, that is not possible!

Thanks,


Ravi Amara :us: (BOB member since 2002-10-02)

Pascal would you please send me the report to gj2002@indiya.com.

Thx…


JaiGupta (BOB member since 2002-09-12)

Hi Pascal,
Would you please send me the report too.
My address is pmelamud@amergent.com

Thanks!


Polina Melamud (BOB member since 2002-09-11)

Hi Pascal…

fancy finding you on a Business Objects forum. Love the VB mate… maybe send the report to me as well ??
I’ve got a question for you. Is it possible with the reporter object model, to select a few cells in a crosstab and determine the context values of those cells. eg. the crosstab has years across the top and products down the side. I select a cell in the body of the crosstab and want the code to determine that , for example , the cell is representative of
1999 - WoollyJumpers
what’s that I hear you say ? free consultancy

Are you now based in Sydney ??
cheers ears
Andy (Richmond)


richmona :australia: (BOB member since 2003-04-15)