Question Excel - Late binding

Pat Hartman

Super Moderator
Staff member
Local time
Yesterday, 21:56
Joined
Feb 19, 2002
Messages
47,090
I have to convert to late binding and what a PITA. I changed the dim statements and I added all the constants and at least 60% of the lines of code throw errors at run time. Usually "Error 438 - Object doesn't support this property or method". I've figured out how to fix most but at the moment, I can't solve this one -
Code:
    Selection.SpecialCells(xlCellTypeLastCell).Select
    iRows = Selection.Row
I'm trying to get the location of the last cell so I can insert some totals on the next line. The first line is what I got using the macro recorder in Excel and it worked fine using Early binding and I figured out the second line by trial and error. For Late binding, prefixing everything with objSht. fixed a lot of stuff but not this.

So - I need to find the last cell and store the row number in a variable. And if you're feeling kindly, insert sums, one row down in columns J and H for J6:Jirows and H6:Hirows.

This is the code I got from Tony Toews site that does conditional compilation:
Code:
' 0 if Late Binding
' 1 if Reference to Excel set.
#Const ExcelRef = 1
#If ExcelRef = 0 Then ' Late binding
    Dim objXL As Object     'Excel Object
    Dim objWkb As Object    'Workbook Object
    Dim objSht As Object    'Sheet Object
    Dim objTemplate As Object   'Workbook Object for Template

    Set objXL = CreateObject("Excel.Application")
    ' Remove the Excel reference if it is present   -   <=======
    On Error Resume Next
    Set ref = References!Excel
    If Err.Number = 0 Then
        References.Remove ref
    ElseIf Err.Number <> 9 Then 'Subscript out of range meaning not reference not found
        MsgBox Err.Description
        Exit Sub
    End If
' Use your own error handling label here
On Error GoTo FormatWeeklyJobStatus_Error
#Else
    ' a reference to MS Excel <version number> Object Library must be specified
    Dim objXL As Excel.Application      'Excel Object
    Dim objWkb As Excel.Workbook        'Workbook Object
    Dim objSht As Excel.Worksheet       'Sheet Object
    Dim objTemplate As Excel.Workbook   'Workbook Object for Template

    Set objXL = New Excel.Application
#End If

Can't fix this one either:
Code:
'freeze panes
    objSht.Range("A6").Select
    objSht.ActiveWindow.FreezePanes = True
How to I position to row 6 and freeze panes?

And another one:
Code:
'set font and size
    objSht.Cells.Select
    With objSht.Selection.Font
        .Name = "Calibri"
        .Size = 11
        .Strikethrough = False
        .Superscript = False
        .Subscript = False
        .OutlineFont = False
        .Shadow = False
        .Underline = xlUnderlineStyleNone
        .TintAndShade = 0
        .ThemeFont = xlThemeFontMinor
    End With
I'm trying to change the font and size for the whole sheet. ObjSht.Cells.Select works but not ObjSht.Selection.Font. Most of the issues I have revolve around referencing something I selected and the code generated by the macro recorder doesn't seem to translate directly into Access VBA.
 
Last edited:
Code:
    objWkb.SpecialCells(xlCellTypeLastCell).Select    
    iRows = objWkb.Selection.Row
This compiles if I have the Excel library referenced but I can't tell if it works since the code is failing before I get there.

I am thoroughly confused. I don't understand why SpecialCells is a property of the workbook rather than the spreadsheet. The code won't compile if I use objSht. as the "expression". How does it know which sheet it should find the last cell for?????

thanks for trying. That's it for me for today.
 
I'm confused to, in excel you would do something like this

Worksheets("Sheet1").Activate
ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Activate

According to ms but I would probably try

Worksheets("Sheet1").Cells.SpecialCells(xlCellTypeLastCell).Select

Don't know how to translate that into late binding

Brian
 
Pat.

Code:
' 0 if Late Binding
' 1 if Reference to Excel set.
#Const ExcelRef = 1
#If ExcelRef = 0 Then ' Late binding
    Dim objXL As Object     'Excel Object
    Dim objWkb As Object    'Workbook Object
    Dim objSht As Object    'Sheet Object
    Dim objTemplate As Object   'Workbook Object for Template

    Set objXL = CreateObject("Excel.Application")
    ' Remove the Excel reference if it is present   -   <=======
    On Error Resume Next
    Set ref = References!Excel
    If Err.Number = 0 Then
        References.Remove ref
    ElseIf Err.Number <> 9 Then 'Subscript out of range meaning not reference not found
        MsgBox Err.Description
        Exit Sub
    End If
' Use your own error handling label here
On Error GoTo FormatWeeklyJobStatus_Error
#Else
    ' a reference to MS Excel <version number> Object Library must be specified
    Dim objXL As Excel.Application      'Excel Object
    Dim objWkb As Excel.Workbook        'Workbook Object
    Dim objSht As Excel.Worksheet       'Sheet Object
    Dim objTemplate As Excel.Workbook   'Workbook Object for Template

    Set objXL = New Excel.Application
#End If

The above code will not compile under any circumstance unless it’s inside a procedure.

Can you please post all the code and a sample Excel application to test it against?

Chris.
 
Having a quick browse before going out for the day came across this discussion on freeze panes.

http://www.utteraccess.com/forum/lofiversion/index.php/t2005603.html

I also noticed that bob Larson had helped on late binding on this forum, without seeing all of your code I don't know if you have defined the constants for all of the xl... Type constants.
As you can manipulated cells without selecting them I rarely use select and noticed that the above discussion mentioned problems, unfortunately the macro recorder always uses select, in fact I found that it tended to create code that needed a lot of tweaking to be useful in an application.

Brian
 
This is the entire procedure. It does not work. The references to the Excel objects are incorrect but I don't know how to fix them. I marked the statements that produce error messages. I also posted the code that does work with early binding so you can see the changes I made to it.

This is the statement (from an earlier procedure) that creates the spreadsheet. It has a problem also. It includes the column headers even though the argument to do so is set to false.
Code:
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, Me.txtExcelQueryName, strFileName, False
Code:
Private Sub FormatWeeklyJobStatus(sFileName)

Const xlDown = -4121
Const xlCellTypeLastCell = 11
Const xlThemeFontMinor = 2
Const xlPrintNoComments = -4142
Const xlPortrait = 1
Const xlPaperLegal = 5
Const xlPaperLetter = 1
Const xlOverThenDown = 2
Const xlPrintErrorsDisplayed = 0

Dim sHeader As String
Dim sPath As String
Dim sRange As String
Dim sColor As Integer
Dim sTemplateName As String
Dim iRows As Integer

Dim ref As Reference

' 0 if Late Binding
' 1 if Reference to Excel set.
#Const ExcelRef = 0
#If ExcelRef = 0 Then ' Late binding
    Dim objXL As Object     'Excel Object
    Dim objWkb As Object    'Workbook Object
    Dim objSht As Object    'Sheet Object
    Dim objTemplate As Object   'Workbook Object for Template

    Set objXL = CreateObject("Excel.Application")
    ' Remove the Excel reference if it is present   -   <=======
    On Error Resume Next
    Set ref = References!Excel
    If Err.Number = 0 Then
        References.Remove ref
    ElseIf Err.Number <> 9 Then 'Subscript out of range meaning not reference not found
        MsgBox Err.Description
        Exit Sub
    End If
' Use your own error handling label here
On Error GoTo FormatWeeklyJobStatus_Error
#Else
    ' a reference to MS Excel <version number> Object Library must be specified
    Dim objXL As Excel.Application      'Excel Object
    Dim objWkb As Excel.Workbook        'Workbook Object
    Dim objSht As Excel.Worksheet       'Sheet Object
    Dim objTemplate As Excel.Workbook   'Workbook Object for Template

    Set objXL = New Excel.Application
#End If

   On Error GoTo FormatWeeklyJobStatus_Error

    sPath = DLookup("Database", "MsysObjects", "[Name] = 'tblJob'") 'find location of BE
    sPath = Left(sPath, InStrRev(sPath, "\"))
    sTemplateName = sPath & "WeeklyJobStatusHeaders.xlsx"

    Set objWkb = objXL.Workbooks.Open(sFileName)
    Set objSht = objXL.Worksheets("qWeeklyJobStatusReportExcel")
    
'make workbook visible
    ''objXL.Visible = True
    
'Set the general number format.  It will be overridden as necessary
    objSht.Cells.NumberFormat = "#,##0_);[Red](#,##0)"

'insert 5 rows at top to make room for headers
    objSht.Rows("1:1").Select
    
    objSht.Rows.Insert Shift:=xlDown    '<=================== error 1004 (to prevent possible loss of data, Excel cannot shift nonblank cells off the workbook
    objSht.Rows.Insert Shift:=xlDown    '<=================== error 1004 (to prevent possible loss of data, Excel cannot shift nonblank cells off the workbook
    objSht.Rows.Insert Shift:=xlDown    '<=================== error 1004 (to prevent possible loss of data, Excel cannot shift nonblank cells off the workbook
    objSht.Rows.Insert Shift:=xlDown    '<=================== error 1004 (to prevent possible loss of data, Excel cannot shift nonblank cells off the workbook
    objSht.Rows.Insert Shift:=xlDown    '<=================== error 1004 (to prevent possible loss of data, Excel cannot shift nonblank cells off the workbook
    objSht.Rows("1:5").Select
'get headers from template file
    Set objTemplate = objXL.Workbooks.Open(sTemplateName)
    objTemplate.Activate
    objSht.Rows("1:5").Select           '<=============== error 1004 (select method of range class failed)
    objSht.Rows("1:5").Copy
    objWkb.Activate
    objSht.Paste
    
'close template
    objXL.CutCopyMode = False    'clear clipboard to get rid of warning message
    objTemplate.Close
'count rows
    objWkb.SpecialCells(xlCellTypeLastCell).Select  '<============== error 438 object does not support this property or method
    iRows = objWkb.Selection.Row                    '<============== error 438 object does not support this property or method
    
'freeze panes
    objSht.Range("A6").Select
    objSht.ActiveWindow.FreezePanes = True          '<============== error 438 object does not support this property or method

'autofit first column
    objSht.Columns("A:A").EntireColumn.AutoFit

'Header should print on every page when in Print Preview
    objSht.PageSetup.PrintTitleRows = "$1:$5"
    objSht.PageSetup.PrintTitleColumns = ""
    
'set format for date columns
    objSht.Columns("H").NumberFormat = "d-mmm;@"
    objSht.Columns("J").NumberFormat = "d-mmm;@"

'set font and size
    objSht.Cells.Select
    With objSht.Selection.Font              '<============== error 438 object does not support this property or method
        .Name = "Calibri"
        .Size = 11
        .Strikethrough = False
        .Superscript = False
        .Subscript = False
        .OutlineFont = False
        .Shadow = False
        .Underline = xlUnderlineStyleNone
        .TintAndShade = 0
        .ThemeFont = xlThemeFontMinor
    End With
    
'set page setup properties
    objSht.Columns("A:N").Select
    objSht.Columns.AutoFit
    objSht.PageSetup.PrintArea = ""
    With objSht.PageSetup
        .LeftHeader = ""
        .CenterHeader = ""
        .RightHeader = ""
        .LeftFooter = ""
        .CenterFooter = ""
        .RightFooter = ""
        .LeftMargin = objXL.InchesToPoints(0.5)
        .RightMargin = objXL.InchesToPoints(0.5)
        .TopMargin = objXL.InchesToPoints(0.5)
        .BottomMargin = objXL.InchesToPoints(0.5)
        .HeaderMargin = objXL.InchesToPoints(0.5)
        .FooterMargin = objXL.InchesToPoints(0.5)
        .PrintHeadings = False
        .PrintGridlines = True
        .PrintComments = xlPrintNoComments
'        .PrintQuality = 600
        .CenterHorizontally = False
        .CenterVertically = False
        .Orientation = xlPortrait
        .Draft = False
        If iRows > 44 Then
            .PaperSize = xlPaperLegal
        Else
            .PaperSize = xlPaperLetter
        End If
        .FirstPageNumber = xlAutomatic
        .Order = xlOverThenDown 'change order to print all "page 1" before "page 2"
        .BlackAndWhite = False
        ''.Zoom = 80 'shrink down a little
        .Zoom = False
        .FitToPagesWide = 1
        .FitToPagesTall = False
        .PrintErrors = xlPrintErrorsDisplayed
    End With

'save workbook
    objWkb.Save
FormatWeeklyJobStatus_Exit:

    objWkb.Close
    Set objSht = Nothing
    Set objWkb = Nothing
    Set objXL = Nothing
   Exit Sub

FormatWeeklyJobStatus_Error:
    Select Case Err.Number
        Case Else
            MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure FormatWeeklyJobStatus of VBA Document Form_frmReports"
    End Select
    Exit Sub
    Resume Next
End Sub
Code that works with Early binding
Code:
Private Sub FormatWeeklyJobStatus(sFileName)

'''commented out because I could't get early binding to work.
Dim appExcel As Excel.Application
Dim wbkNew As Excel.Workbook
Dim wbkTemplate As Excel.Workbook
Dim wksNew As Excel.Worksheet
Dim sHeader As String
Dim sPath As String
Dim sRange As String
Dim sColor As Integer
Dim sTemplateName As String
Dim iRows As Integer

'Change this if you want the path to be other than the R: drive change tblFileLocation

   On Error GoTo FormatWeeklyJobStatus_Error

    sPath = DLookup("Database", "MsysObjects", "[Name] = 'tblJob'") 'find location of BE
    sPath = Left(sPath, InStrRev(sPath, "\"))
    sTemplateName = sPath & "WeeklyJobStatusHeaders.xlsx"
    Set appExcel = Excel.Application
    Set wbkNew = appExcel.Workbooks.Open(sFileName)
    Set wksNew = appExcel.Worksheets("qWeeklyJobStatusReportExcel")
'make workbook visible
    ''appExcel.Visible = True
'Set the general number format.  It will be overridden as necessary
    Cells.NumberFormat = "#,##0_);[Red](#,##0)"

'insert 5 rows at top to make room for headers
    Rows("1:1").Select
    Selection.Insert Shift:=xlDown
    Selection.Insert Shift:=xlDown
    Selection.Insert Shift:=xlDown
    Selection.Insert Shift:=xlDown
    Selection.Insert Shift:=xlDown
    Rows("1:5").Select
'get headers from template file
    Set wbkTemplate = appExcel.Workbooks.Open(sTemplateName)
    wbkTemplate.Activate
    Rows("1:5").Select
    Selection.Copy
    wbkNew.Activate
    ActiveSheet.Paste
'close template
    appExcel.CutCopyMode = False    'clear clipboard to get rid of warning message
    wbkTemplate.Close
'count rows
    Selection.SpecialCells(xlCellTypeLastCell).Select
    iRows = Selection.Row
'freeze panes
    Range("A6").Select
    ActiveWindow.FreezePanes = True
'autofit first column
    Columns("A:A").EntireColumn.AutoFit
'Header should print on every page when in Print Preview
    ActiveSheet.PageSetup.PrintTitleRows = "$1:$5"
    ActiveSheet.PageSetup.PrintTitleColumns = ""
'set format for date columns

    wksNew.Columns("H").NumberFormat = "d-mmm;@"
    wksNew.Columns("J").NumberFormat = "d-mmm;@"

'set font and size
    Cells.Select
    With Selection.Font
        .Name = "Calibri"
        .Size = 11
        .Strikethrough = False
        .Superscript = False
        .Subscript = False
        .OutlineFont = False
        .Shadow = False
        .Underline = xlUnderlineStyleNone
        .TintAndShade = 0
        .ThemeFont = xlThemeFontMinor
    End With
'set page setup properties
    Columns("A:N").Select
    Selection.Columns.AutoFit
    ''''ActiveSheet.PageSetup.PrintArea = "$A:$N"
    ActiveSheet.PageSetup.PrintArea = ""
    With ActiveSheet.PageSetup
        .LeftHeader = ""
        .CenterHeader = ""
        .RightHeader = ""
        .LeftFooter = ""
        .CenterFooter = ""
        .RightFooter = ""
        .LeftMargin = appExcel.InchesToPoints(0.5)
        .RightMargin = appExcel.InchesToPoints(0.5)
        .TopMargin = appExcel.InchesToPoints(0.5)
        .BottomMargin = appExcel.InchesToPoints(0.5)
        .HeaderMargin = appExcel.InchesToPoints(0.5)
        .FooterMargin = appExcel.InchesToPoints(0.5)
        .PrintHeadings = False
        .PrintGridlines = True
        .PrintComments = xlPrintNoComments
'        .PrintQuality = 600
        .CenterHorizontally = False
        .CenterVertically = False
        .Orientation = xlPortrait
        .Draft = False
        If iRows > 44 Then
            .PaperSize = xlPaperLegal
        Else
            .PaperSize = xlPaperLetter
        End If
        .FirstPageNumber = xlAutomatic
        .Order = xlOverThenDown 'change order to print all "page 1" before "page 2"
        .BlackAndWhite = False
        ''.Zoom = 80 'shrink down a little
        .Zoom = False
        .FitToPagesWide = 1
        .FitToPagesTall = False
        .PrintErrors = xlPrintErrorsDisplayed
    End With

'save workbook
    wbkNew.Save
FormatWeeklyJobStatus_Exit:

    wbkNew.Close
    Set wksNew = Nothing
    Set wbkNew = Nothing
    Set appExcel = Nothing
    '''appExce.Quit     'check first to see if this app opened it.
   Exit Sub

FormatWeeklyJobStatus_Error:
    Select Case Err.Number
        Case Else
            MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure FormatWeeklyJobStatus of VBA Document Form_frmReports"
    End Select
End Sub
 
Field names are always exported to a spreadsheet

HasFieldNames
Optional
Variant
Use True (–1) to use the first row of the spreadsheet as field names when importing or linking. Use False (0) to treat the first row of the spreadsheet as normal data. If you leave this argument blank, the default (False) is assumed. When you export Access table or select query data to a spreadsheet, the field names are inserted into the first row of the spreadsheet no matter what you enter for this argument.

Your other problems all appear to be associated with Select, I think you have commented on that, as I said earlier the Utteraccess discussion I posted a link to and a link from that both say that it will give problems and some examples of how to code exist in the links , particularly on freeze panes.

I don't feel competent enough to change the code without being able to test, I'd probably just have to muddle through it now a days

Brian
 
I understand your reluctance to attempt to replicate the problem. That's why I didn't post the entire procedure to begin with but just extracted a couple of items that I was having trouble with.

I wonder if the HasFieldNames issue is a problem with my version of Access (A2010 -14.0.6129.5999 (32-bit)) on Win-7. I've never seen this before. I'm automating the code so it would be easy enough to delete the extraneous row but I'd rather not have to.

The UtterAccess link helped me set the Freeze panes.

I am completely mystified by how different the late binding code has to be. All the web articles say how "easy" it is. You just change how you define the objects and create constants for any Excel/Word/etc. constants you use. Not even close!!!
 
Hi Pat.

Please bear with me because I don’t know much about Excel late binding.

All of the following code was tested in Access from this procedure:-
(I had to change the file extension to XLS.)
Code:
Sub TestIt()
    Dim strFileName As String
    Dim txtExcelQueryName As String
    
    Const acSpreadsheetTypeExcel9 As Long = 8

    strFileName = "C:\NewWeeklyJobStatusHeaders.xls"
    txtExcelQueryName = "qWeeklyJobStatusReportExcel"

    DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, txtExcelQueryName, strFileName, False

    FormatWeeklyJobStatus strFileName
    
End Sub

These are the very much reduced FormatWeeklyJobStatus subroutines, called one at a time, which breaks it down into steps…

Early bound as per original:-
Note that it relies, not only a reference to Excel being set, but also that the lines of code starting with Cell, Rows and Selection being understood by the compiler. But it works because we have a reference to Excel.
Code:
Private Sub FormatWeeklyJobStatus(sFileName)
    Dim appExcel      As Excel.Application
    Dim wbkNew        As Excel.Workbook
    Dim wbkTemplate   As Excel.Workbook
    Dim wksNew        As Excel.Worksheet
    Dim sPath         As String
    Dim sTemplateName As String

    On Error GoTo FormatWeeklyJobStatus_Error

    sPath = DLookup("Database", "MsysObjects", "[Name] = 'tblJob'")
    sPath = Left(sPath, InStrRev(sPath, "\"))
    sTemplateName = sPath & "WeeklyJobStatusHeaders.xls"
    Set appExcel = Excel.Application
    Set wbkNew = appExcel.Workbooks.Open(sFileName)
    Set wksNew = appExcel.Worksheets("qWeeklyJobStatusReportExcel")

    Cells.NumberFormat = "#,##0_);[Red](#,##0)"

    Rows("1:1").Select
    Selection.Insert Shift:=xlDown
    Selection.Insert Shift:=xlDown
    Selection.Insert Shift:=xlDown
    Selection.Insert Shift:=xlDown
    Selection.Insert Shift:=xlDown
    Rows("1:5").Select

    wbkNew.Save

FormatWeeklyJobStatus_Exit:
    On Error Resume Next

    wbkNew.Close
    Set wbkNew = Nothing

    appExcel.Quit
    Set appExcel = Nothing
    Exit Sub

FormatWeeklyJobStatus_Error:
    Select Case Err.Number
        Case Else
            MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure FormatWeeklyJobStatus of VBA Document Form_frmReports"
    End Select

    Resume FormatWeeklyJobStatus_Exit

End Sub

Still early bound but disambiguating the lines of code starting with Cell, Rows and Selection:-
Code:
Private Sub FormatWeeklyJobStatus(sFileName)
    Dim appExcel      As Excel.Application
    Dim wbkNew        As Excel.Workbook
    Dim wbkTemplate   As Excel.Workbook
    Dim wksNew        As Excel.Worksheet
    Dim sPath         As String
    Dim sTemplateName As String

    On Error GoTo FormatWeeklyJobStatus_Error

    sPath = DLookup("Database", "MsysObjects", "[Name] = 'tblJob'")
    sPath = Left(sPath, InStrRev(sPath, "\"))
    sTemplateName = sPath & "WeeklyJobStatusHeaders.xls"
    Set appExcel = Excel.Application
    Set wbkNew = appExcel.Workbooks.Open(sFileName)
    Set wksNew = appExcel.Worksheets("qWeeklyJobStatusReportExcel")

    With appExcel
        .Cells.NumberFormat = "#,##0_);[Red](#,##0)"

        .Rows("1:1").Select
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Rows("1:5").Select
    End With

    wbkNew.Save

FormatWeeklyJobStatus_Exit:
    On Error Resume Next

    wbkNew.Close
    Set wbkNew = Nothing

    appExcel.Quit
    Set appExcel = Nothing
    Exit Sub

FormatWeeklyJobStatus_Error:
    Select Case Err.Number
        Case Else
            MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure FormatWeeklyJobStatus of VBA Document Form_frmReports"
    End Select

    Resume FormatWeeklyJobStatus_Exit

End Sub

Now we have disambiguated those lines of code we can late* bind and remove the the Excel reference:-
Code:
Private Sub FormatWeeklyJobStatus(sFileName)
    Dim appExcel      As Object [color=green]'Excel.Application[/color]
    Dim wbkNew        As Object [color=green]'Excel.Workbook[/color]
    Dim wbkTemplate   As Object [color=green]'Excel.Workbook[/color]
    Dim wksNew        As Object [color=green]'Excel.Worksheet[/color] 
    Dim sPath         As String
    Dim sTemplateName As String

    Const xlDown As Long = -4121
 
    On Error GoTo FormatWeeklyJobStatus_Error

    sPath = DLookup("Database", "MsysObjects", "[Name] = 'tblJob'")
    sPath = Left(sPath, InStrRev(sPath, "\"))
    sTemplateName = sPath & "WeeklyJobStatusHeaders.xls"
    Set appExcel = CreateObject("Excel.Application")    [color=green]'Excel.Application[/color]
    Set wbkNew = appExcel.Workbooks.Open(sFileName)
    Set wksNew = appExcel.Worksheets("qWeeklyJobStatusReportExcel")

    With appExcel
        .Cells.NumberFormat = "#,##0_);[Red](#,##0)"

        .Rows("1:1").Select
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Rows("1:5").Select
    End With

    wbkNew.Save

FormatWeeklyJobStatus_Exit:
    On Error Resume Next

    wbkNew.Close
    Set wbkNew = Nothing

    appExcel.Quit
    Set appExcel = Nothing
    Exit Sub

FormatWeeklyJobStatus_Error:
    Select Case Err.Number
        Case Else
            MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure FormatWeeklyJobStatus of VBA Document Form_frmReports"
    End Select

    Resume FormatWeeklyJobStatus_Exit

End Sub

So the original problem appears to be in not disambiguating some of the lines of code.
Disambiguation is almost always referred to on the www as disambiguation to a declared object as set in references, but it is not. Disambiguation actually means disambiguation to the correct Object Pointer even if that Object Pointer it is not declared with a specific reference Type.

In other words, the compiler needs the correct pointer in order to operate on the correct methods or properties of that pointer.

I would recommend rewriting the original early bound code to refer directly to the Object to which it refers within the specific procedure and not to the reference as set in Tools>References.

Not:-
Cells.NumberFormat = "#,##0_);[Red](#,##0)"
but:-
appExcel.Cells.NumberFormat = "#,##0_);[Red](#,##0)"


Hope that makes some sense???

*Edit.

Chris.
 
Last edited:
Code:
    objWkb.SpecialCells(xlCellTypeLastCell).Select    
    iRows = objWkb.Selection.Row
This compiles if I have the Excel library referenced but I can't tell if it works since the code is failing before I get there.

I am thoroughly confused. I don't understand why SpecialCells is a property of the workbook rather than the spreadsheet. The code won't compile if I use objSht. as the "expression". How does it know which sheet it should find the last cell for?????

thanks for trying. That's it for me for today.


Pat

maybe the xlCellTypeLastCell just uses the active worksheet. that must be a property of the workbook. Also, is xlCellTypeLastCell an actual cell reference or is it a constant
 
I still feel that the problem is with using Select.
I would code for the inserts in excel

Worksheet("sheetname").Range("A1").rows.insert

or

Worksheets("sheetname").Rows("1:4").Insert Shift:=xlDown

no selection necessary.

Note also that xlCellTypeLastCell considers formatted cells to contain information, and deleted rows etc still count until the worksheet is saved. Excel users usually use an xlup type of approach but for total flexibility you might want to consider the option mentioned in the microsoft library chapter5 "using Ranges"
Code:
Dim lastrow as Long

lastrow= Worksheets("sheetname").Cells.Find("*", Range("A1"), xlFormulas, , xlByRows, xlPrevious).Row

This forces Excel to search backwards from A1, ie to wrap round, thus coping with the different max rows between releases.

I presume that with late binding you would simply replace
Worksheet("sheetname") with objsht

Brian
 
Last edited:
Thanks Guys,
I knew the problem was with how the properties/methods were referenced but I didn't work out that many of them belonged to Excel rather than the workbook or worksheet since the help entries simply say "expression.". I'm working on a different project for a different client today but I'll try to fix the app over the weekend.
 
Hi Pat.

I do get bored at times…

The following is a late bound version of the early bound version you supplied.
It will run without any references at all, except the two we can’t remove.
It does not matter if Excel is referenced, the code simply doesn’t use it.

There are two or three things which don’t work with XP but they are minor points and I’ve commented them out.

It’s clean even under a crash condition because it doesn’t leave Excel in memory. It is, and has been, a bit of nonsense to set object variables to Nothing but in this case closing wbkNew is required to remove Excel from memory. If we don’t remove Excel from memory we will get an error message if we run the code more than once.

If you are going to be using late bound Excel a lot I would recommend declaring the Excel constants publicly. They take precedence over the Excel built-in constants even if Excel is declared. There is no interference between user defined constants and built-in constants.

At this point, I don’t see a reason for Tony Toews’ conditional compilation code. Maybe we can talk about that once the late bound code is working.

So for the late bound code:-
Code:
Option Compare Database
Option Explicit

Public Const acSpreadsheetTypeExcel9   As Long = 8
Public Const xlDown                    As Long = -4121
Public Const xlCellTypeLastCell        As Long = 11
Public Const xlUnderlineStyleNone      As Long = -4142
Public Const xlPrintNoComments         As Long = -4142
Public Const xlPaperLegal              As Long = 5
Public Const xlPaperLetter             As Long = 1
Public Const xlPortrait                As Long = 1
Public Const xlAutomatic               As Long = -4105
Public Const xlOverThenDown            As Long = 2
Public Const xlPrintErrorsDisplayed    As Long = 0
' Public   Const xlThemeFontMinor       As Long = ???    ' Can't test this in XP.


Sub TestIt()
    Dim strFileName       As String
    Dim txtExcelQueryName As String
    
    strFileName = "C:\NewWeeklyJobStatusHeaders.xls"
    txtExcelQueryName = "qWeeklyJobStatusReportExcel"

    ' I simply got tired of deleting the old destination file, we will create a new one.
    On Error Resume Next
        Kill strFileName
    On Error GoTo 0

    DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, txtExcelQueryName, strFileName, False

    FormatWeeklyJobStatus strFileName
    
End Sub


Private Sub FormatWeeklyJobStatus(sFileName)
    Dim appExcel      As Object
    Dim wbkNew        As Object
    Dim wbkTemplate   As Object
    Dim wksNew        As Object
    Dim sPath         As String
    Dim sTemplateName As String
    Dim lngRows       As Long

    On Error GoTo FormatWeeklyJobStatus_Error

    sPath = DLookup("Database", "MsysObjects", "[Name] = 'tblJob'")
    sPath = Left(sPath, InStrRev(sPath, "\"))
    sTemplateName = sPath & "WeeklyJobStatusHeaders.xls"
    Set appExcel = CreateObject("Excel.Application")
    Set wbkNew = appExcel.Workbooks.Open(sFileName)
    Set wksNew = appExcel.Worksheets("qWeeklyJobStatusReportExcel")
    
    ' Insert 5 rows at top to make room for headers
    With appExcel
        .Cells.NumberFormat = "#,##0_);[Red](#,##0)"
    
        .Rows("1:1").Select
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        .Selection.Insert Shift:=xlDown
        
        ' Get headers from template file
        Set wbkTemplate = .Workbooks.Open(sTemplateName)
        wbkTemplate.Activate
        .Rows("1:5").Select
        .Selection.Copy
        ' Paste into new Workbook.
        wbkNew.Activate
        .ActiveSheet.Paste
        ' Close template
        .CutCopyMode = False    'clear clipboard to get rid of warning message
        wbkTemplate.Close
        
        ' Count rows in new Workbook.
        .Selection.SpecialCells(xlCellTypeLastCell).Select
        lngRows = .Selection.Row
        
        ' Freeze panes
        .Range("A6").Select
        .ActiveWindow.FreezePanes = True
        
        ' Autofit first column
        .Columns("A:A").EntireColumn.AutoFit
        
        ' Header should print on every page when in Print Preview
        .ActiveSheet.PageSetup.PrintTitleRows = "$1:$5"
        .ActiveSheet.PageSetup.PrintTitleColumns = ""
        
        ' Set format for date columns
        wksNew.Columns("H").NumberFormat = "d-mmm;@"
        wksNew.Columns("J").NumberFormat = "d-mmm;@"
        
        ' Set font and size
        .Cells.Select
        With .Selection.Font
            .Name = "Calibri"
            .Size = 11
            .Strikethrough = False
            .Superscript = False
            .Subscript = False
            .OutlineFont = False
            .Shadow = False
            .Underline = xlUnderlineStyleNone
        '   .TintAndShade = 0               ' Don't know about this one.
        '   .ThemeFont = xlThemeFontMinor   ' Can't test this in XP.
        End With
        
        ' Set page setup properties
        .Columns("A:N").Select
        .Selection.Columns.AutoFit
        
        With .ActiveSheet.PageSetup
            ' I don't know the intention here...
            '    .PrintArea = "$A:$N"
            '    .PrintArea = ""
            .PrintArea = "$A$1:$N$" & CStr(lngRows)

            .LeftHeader = ""
            .CenterHeader = ""
            .RightHeader = ""
            .LeftFooter = ""
            .CenterFooter = ""
            .RightFooter = ""
            .LeftMargin = appExcel.InchesToPoints(0.5)
            .RightMargin = appExcel.InchesToPoints(0.5)
            .TopMargin = appExcel.InchesToPoints(0.5)
            .BottomMargin = appExcel.InchesToPoints(0.5)
            .HeaderMargin = appExcel.InchesToPoints(0.5)
            .FooterMargin = appExcel.InchesToPoints(0.5)
            .PrintHeadings = False
            .PrintGridlines = True
            .PrintComments = xlPrintNoComments
            .PrintQuality = 600
            .CenterHorizontally = False
            .CenterVertically = False
            .Orientation = xlPortrait
            .Draft = False
            .PaperSize = IIf(lngRows > 44, xlPaperLegal, xlPaperLetter)
            .FirstPageNumber = xlAutomatic
            .Order = xlOverThenDown                         ' Change order to print all "page 1" before "page 2"
            .BlackAndWhite = False
            .Zoom = 80                                      ' Shrink down a little
            .Zoom = False                                   ' Should not need both
            .FitToPagesWide = 1
            .FitToPagesTall = False
            .PrintErrors = xlPrintErrorsDisplayed
        End With
    End With

    wbkNew.Save

FormatWeeklyJobStatus_Exit:
    On Error Resume Next
    ' Required for cleanup.
    wbkNew.Close
    Exit Sub

FormatWeeklyJobStatus_Error:
    Select Case Err.Number
        Case Else
            MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure FormatWeeklyJobStatus of VBA Document Form_frmReports"
    End Select

    Resume FormatWeeklyJobStatus_Exit

End Sub

Hope that helps.

Chris.
 
I am not an Excel "guru" , in fact my Excel knowledge and experience is similar to my Access, too little to know how little I know, but I have read across many forums that the use of Active... And Select should be avoided as problems may, some say will, occur more especially if more than one workbook is open.
The Select has performance implications as it causes activity on the screen.

Chris I would be interested in any comments you care to make on this.

Brian
 
Brian.

First up let me say I know far less about Excel than most people and that is because I have seldom used it.

In this case, however, I do not need to know very much about Excel; all I need to know about is late binding. You see, Pat posted the early bound code and said it worked. Pat also posted the method to test it.

All I had to do was reproduce the early bound test case, as supplied by Pat, and make sure that what I reproduced worked properly. Then the only thing to be done was to re-write the code in a late bound style and make sure it still works without a reference to Excel.

So, technically speaking, I did not have to know how the early bound code worked, I can believe Pat when she says it works properly. All I have to do is convert the code without breaking it.

----------

As for the use of Active and Select, maybe yes maybe no, I don’t know. But Excel forums are probably the same as Access forums. What that means is that a lot of ‘stuff’ is very likely to be simply repeated across forums by people who have not tested it and simply don’t know.

Mostly the people who simply repeat things will not give details as to the circumstances of the possible failure. Quite often it is not what is being done which causes the failure but rather the circumstances under which it is being done. But the people who simply repeat what they read don’t know the circumstances so all they do is repeat what they read. And I see no reason to believe that Excel forums should be any different to Access forums in that regard.

----------

>>The Select has performance implications as it causes activity on the screen.<<
Well it might but in this case it doesn’t.
In post #7, Pat had the line of code appExcel.Visible = True but commented it out.
I put it back in for testing and it does cause needless screen flicker. It also leaves a copy of Excel open and the end user would have to close it. So I took it out again because it is not needed. Now the application runs without ‘activity on the screen’ so that is no longer a consideration.

If it is required for the end user to see the new workbook then:-
wbkNew.Save
appExcel.Visible = True
and remove the wbkNew.Close in the FormatWeeklyJobStatus_Exit: section.
(I would not do that, however. I would build it, close it and re-open it again in code for printing.)

----------

So my general comment is that someone has to do the actual work in order to get the job done. That is why I asked for the full code in post #5.

Chris.
 
And here is something else that may be of interest in using constants in either early or late bound code:-
http://www.access-programmers.co.uk/forums/showthread.php?t=241058
It is a secondary consideration but it does supply Intellisense with constants.
(A demo of the FE is attached if you wish to see how the constants works.)

The primary consideration, as I see it, is to prevent Excel from having a single instance of the destination file strFileName open when the code runs. It is also imperative that the destination file does not exist when the code is run.

To that end we shutdown any instance of Excel which may be holding that file open and also Kill the file. The function also needs to handle itself and close Excel. It also seems prudent for the function to not display the error but instead pass the error back to the caller. The caller can then decide how to handle the error or, in deed, open the Excel application if required.

Therefore, the code as it stands, with Class constants, shutting down Excel, passing back the error code and optionally displaying the Excel application is as such:-
Code:
Option Explicit
Option Compare Text

Public con As New clsConstants


Sub TestIt()
    Dim lngError     As Long
    Dim strFileName  As String
    Dim strQueryName As String
    
    strFileName = "C:\NewWeeklyJobStatusHeaders.xls"
    strQueryName = "qWeeklyJobStatusReportExcel"

    On Error Resume Next
        [color=green]' Remove any instance of Excel which may have strFileName already open.
        ' This can happen if the end user minimisers Excel and runs the code a second time.[/color]
        GetObject(strFileName).Close
        
        [color=green]' Kill any pre-existing file called strFileName, we will create a new one.[/color]
        Kill strFileName
    On Error GoTo 0

    DoCmd.TransferSpreadsheet acExport, con.Excel.acSpreadsheetTypeExcel9, strQueryName, strFileName, False

    [color=green]' Call the function and return the error code.[/color]
    lngError = FormatWeeklyJobStatus(strFileName)
    
    If lngError Then
        MsgBox "Error " & lngError & " (" & Error(lngError) & ") in procedure FormatWeeklyJobStatus"
    Else
        [color=green]' Open the new instance for display to the end user, if required.[/color]
        With CreateObject("Excel.Application")
            .Workbooks.Open strFileName
            .Visible = True
        End With
    End If
    
End Sub


Private Function FormatWeeklyJobStatus(sFileName) As Long
    Dim appExcel      As Object
    Dim wbkNew        As Object
    Dim wbkTemplate   As Object
    Dim wksNew        As Object
    Dim sPath         As String
    Dim sTemplateName As String
    Dim lngRows       As Long
    
    On Error GoTo FormatWeeklyJobStatus_Error
    
    sPath = DLookup("Database", "MsysObjects", "[Name] = 'tblJob'")
    sPath = Left(sPath, InStrRev(sPath, "\"))
    sTemplateName = sPath & "WeeklyJobStatusHeaders.xls"
    Set appExcel = CreateObject("Excel.Application")
    Set wbkNew = appExcel.Workbooks.Open(sFileName)
    Set wksNew = appExcel.Worksheets("qWeeklyJobStatusReportExcel")
    
    ' Insert 5 rows at top to make room for headers
    With appExcel
        .Cells.NumberFormat = "#,##0_);[Red](#,##0)"
    
        .Rows("1:1").Select
        .Selection.Insert Shift:=con.Excel.xlDown
        .Selection.Insert Shift:=con.Excel.xlDown
        .Selection.Insert Shift:=con.Excel.xlDown
        .Selection.Insert Shift:=con.Excel.xlDown
        .Selection.Insert Shift:=con.Excel.xlDown
        
        ' Get headers from template file
        Set wbkTemplate = .Workbooks.Open(sTemplateName)
        wbkTemplate.Activate
        .Rows("1:5").Select
        .Selection.Copy
        ' Paste into new Workbook.
        wbkNew.Activate
        .ActiveSheet.Paste
        ' Close template
        .CutCopyMode = False    ' clear clipboard to get rid of warning message
        wbkTemplate.Close

        ' Count rows in new Workbook.
        .Selection.SpecialCells(con.Excel.xlCellTypeLastCell).Select
        lngRows = .Selection.Row
        
        ' Freeze panes
        .Range("A6").Select
        .ActiveWindow.FreezePanes = True
        
        ' Autofit first column
        .Columns("A:A").EntireColumn.AutoFit
        
        ' Header should print on every page when in Print Preview
        .ActiveSheet.PageSetup.PrintTitleRows = "$1:$5"
        .ActiveSheet.PageSetup.PrintTitleColumns = ""
        
        ' Set format for date columns
        wksNew.Columns("H").NumberFormat = "d-mmm;@"
        wksNew.Columns("J").NumberFormat = "d-mmm;@"
        
        ' Set font and size
        .Cells.Select
        With .Selection.Font
            .Name = "Calibri"
            .Size = 11
            .Strikethrough = False
            .Superscript = False
            .Subscript = False
            .OutlineFont = False
            .Shadow = False
            .Underline = con.Excel.xlUnderlineStyleNone
        '   .TintAndShade = 0                         ' Don't know about this one.
        '   .ThemeFont = con.EXCEL.xlThemeFontMinor   ' Can't test this in XP.
        End With
        
        ' Set page setup properties
        .Columns("A:N").Select
        .Selection.Columns.AutoFit
        
        With .ActiveSheet.PageSetup
            ' I don't know the intention here...
            '    .PrintArea = "$A:$N"
            '    .PrintArea = ""
            .PrintArea = "$A$1:$N$" & CStr(lngRows)

            .LeftHeader = ""
            .CenterHeader = ""
            .RightHeader = ""
            .LeftFooter = ""
            .CenterFooter = ""
            .RightFooter = ""
            .LeftMargin = appExcel.InchesToPoints(0.5)
            .RightMargin = appExcel.InchesToPoints(0.5)
            .TopMargin = appExcel.InchesToPoints(0.5)
            .BottomMargin = appExcel.InchesToPoints(0.5)
            .HeaderMargin = appExcel.InchesToPoints(0.5)
            .FooterMargin = appExcel.InchesToPoints(0.5)
            .PrintHeadings = False
            .PrintGridlines = True
            .PrintComments = con.Excel.xlPrintNoComments
            .PrintQuality = 600
            .CenterHorizontally = False
            .CenterVertically = False
            .Orientation = con.Excel.xlPortrait
            .Draft = False
            .PaperSize = IIf(lngRows > 44, con.Excel.xlPaperLegal, con.Excel.xlPaperLetter)
            .FirstPageNumber = con.Excel.xlAutomatic
            .Order = con.Excel.xlOverThenDown               ' Change order to print all "page 1" before "page 2"
            .BlackAndWhite = False
            .Zoom = 80                                      ' Shrink down a little
            .Zoom = False                                   ' Should not need both
            .FitToPagesWide = 1
            .FitToPagesTall = False
            .PrintErrors = con.Excel.xlPrintErrorsDisplayed
        End With
    End With

FormatWeeklyJobStatus_Exit:
    On Error Resume Next
    [color=green]' Required for cleanup.[/color]
    wbkNew.Save
    wbkNew.Close
    Exit Function

FormatWeeklyJobStatus_Error:
    FormatWeeklyJobStatus = Err.Number  [color=green]' Save the error.[/color]
    Resume FormatWeeklyJobStatus_Exit   [color=green]' Clear the error and cleanup.[/color]

End Function

Chris.
 

Attachments

The calculated cells:-
Code:
[color=green]' Set calculated cells formula.[/color]
strCol = "I"
.Cells(lngRows, strCol).Value = "=SUM(" & strCol & conHeaderRows + 1 & ":" & strCol & lngRows - 1 & ")"
strCol = "K"
.Cells(lngRows, strCol).Value = "=SUM(" & strCol & conHeaderRows + 1 & ":" & strCol & lngRows - 1 & ")"

Last modification:-
Code:
Sub TestIt()
    Dim lngError     As Long
    Dim strFileName  As String
    Dim strQueryName As String
    
    strFileName = "C:\NewWeeklyJobStatusHeaders.xls"
    strQueryName = "qWeeklyJobStatusReportExcel"

    On Error Resume Next
        [color=green]' Remove any instance of Excel which may have strFileName already open.
        ' This can happen if the end user minimisers Excel and runs the code a second time.
        ' Since the application has calculated cells, let's avoid the message to save.[/color]
        GetObject(strFileName).Close SaveChanges:=False

        ' Kill any pre-existing file called strFileName, we will create a new one.
        Kill strFileName
    On Error GoTo 0

    DoCmd.TransferSpreadsheet acExport, con.Excel.acSpreadsheetTypeExcel9, strQueryName, strFileName, False

    ' Call the function and return the error code.
    lngError = FormatWeeklyJobStatus(strFileName)
    
    If lngError Then
        MsgBox "Error " & lngError & " (" & Error(lngError) & ") in procedure FormatWeeklyJobStatus"
    Else
        ' Open the new instance for display to the end user, if required.
        With CreateObject("Excel.Application")
            .Workbooks.Open strFileName
            .Visible = True
        End With
    End If
    
End Sub


Private Function FormatWeeklyJobStatus(sFileName) As Long
    Dim appExcel      As Object
    Dim wbkNew        As Object
    Dim wbkTemplate   As Object
    Dim wksNew        As Object
    Dim sPath         As String
    Dim sTemplateName As String
    Dim lngRows       As Long
    Dim strCol        As String
    
    ' Since we use this throughout the procedure it should be a constant.
    Const conHeaderRows As Long = 5
    
    On Error GoTo FormatWeeklyJobStatus_Error
    
    sPath = DLookup("Database", "MsysObjects", "[Name] = 'tblJob'")
    sPath = Left(sPath, InStrRev(sPath, "\"))
    sTemplateName = sPath & "WeeklyJobStatusHeaders.xls"
    Set appExcel = CreateObject("Excel.Application")
    Set wbkNew = appExcel.Workbooks.Open(sFileName)
    Set wksNew = appExcel.Worksheets("qWeeklyJobStatusReportExcel")
    
    With appExcel
        ' Delete the Header appended from the Query result.
        .Rows(1).Delete
    
        ' Insert conHeaderRows at top to make room for headers
        .Rows("1:1").Select
        For lngRows = 1 To conHeaderRows
            .Selection.Insert Shift:=con.Excel.xlDown
        Next lngRows
        
        ' Get headers from template file
        Set wbkTemplate = .Workbooks.Open(sTemplateName)
        
        .Rows("1:" & conHeaderRows).Select
        .Selection.Copy
        ' Paste into new Workbook.
        wbkNew.Activate
        .ActiveSheet.Paste
        ' Close template
        .CutCopyMode = False    ' clear clipboard to get rid of warning message
        wbkTemplate.Close SaveChanges:=False

        ' Count rows in new Workbook
        .Selection.SpecialCells(con.Excel.xlCellTypeLastCell).Select
        lngRows = .Selection.Row
        
        ' Freeze panes
        .Range("A" & conHeaderRows + 1).Select
        .ActiveWindow.FreezePanes = True

        ' Autofit first column
        .Columns("A:A").EntireColumn.AutoFit

        ' Header should print on every page when in Print Preview
        .ActiveSheet.PageSetup.PrintTitleRows = "$1:$" & conHeaderRows
        .ActiveSheet.PageSetup.PrintTitleColumns = ""

        ' Set format for numbers
        .Cells.NumberFormat = "#,##0_);[Red](#,##0)"

        ' Set format for date columns
        wksNew.Columns("H").NumberFormat = "d-mmm;@"
        wksNew.Columns("J").NumberFormat = "d-mmm;@"

        ' Set calculated cells formula.
        strCol = "I"
        appExcel.Cells(lngRows, strCol).Value = "=SUM(" & strCol & conHeaderRows + 1 & ":" & strCol & lngRows - 1 & ")"
        strCol = "K"
        appExcel.Cells(lngRows, strCol).Value = "=SUM(" & strCol & conHeaderRows + 1 & ":" & strCol & lngRows - 1 & ")"
        
        ' Set font and size
        .Cells.Select
        With .Selection.Font
            .Name = "Calibri"
            .Size = 11
            .Strikethrough = False
            .Superscript = False
            .Subscript = False
            .OutlineFont = False
            .Shadow = False
            .Underline = con.Excel.xlUnderlineStyleNone
        '   .TintAndShade = 0                         ' Don't know about this one.
        '   .ThemeFont = con.EXCEL.xlThemeFontMinor   ' Can't test this in XP.
        End With

        ' Set page setup properties
        .Columns("A:N").Select
        .Selection.Columns.AutoFit

        With .ActiveSheet.PageSetup
            ' I don't know the intention here...
            '    .PrintArea = "$A:$N"
            '    .PrintArea = ""
            .PrintArea = "$A$1:$N$" & CStr(lngRows)

            .LeftHeader = ""
            .CenterHeader = ""
            .RightHeader = ""
            .LeftFooter = ""
            .CenterFooter = ""
            .RightFooter = ""
            .LeftMargin = appExcel.InchesToPoints(0.5)
            .RightMargin = appExcel.InchesToPoints(0.5)
            .TopMargin = appExcel.InchesToPoints(0.5)
            .BottomMargin = appExcel.InchesToPoints(0.5)
            .HeaderMargin = appExcel.InchesToPoints(0.5)
            .FooterMargin = appExcel.InchesToPoints(0.5)
            .PrintHeadings = False
            .PrintGridlines = True
            .PrintComments = con.Excel.xlPrintNoComments
            .PrintQuality = 600
            .CenterHorizontally = False
            .CenterVertically = False
            .Orientation = con.Excel.xlPortrait
            .Draft = False
            .PaperSize = IIf(lngRows > 44, con.Excel.xlPaperLegal, con.Excel.xlPaperLetter)
            .FirstPageNumber = con.Excel.xlAutomatic
            .Order = con.Excel.xlOverThenDown               ' Change order to print all "page 1" before "page 2"
            .BlackAndWhite = False
            .Zoom = 80                                      ' Shrink down a little
            .Zoom = False                                   ' Should not need both
            .FitToPagesWide = 1
            .FitToPagesTall = False
            .PrintErrors = con.Excel.xlPrintErrorsDisplayed
        End With
    End With

FormatWeeklyJobStatus_Exit:
    On Error Resume Next
    ' Required for cleanup.
    wbkNew.Close SaveChanges:=True
    Exit Function

FormatWeeklyJobStatus_Error:
    FormatWeeklyJobStatus = Err.Number  ' Save the error.
    Resume FormatWeeklyJobStatus_Exit   ' Clear the error and cleanup.

End Function

Chris.
 
Thanks to you all, I am very close. I have one more syntax hurdle to cross. I want to insert sums at the bottom of several columns. I have iRows which is the number of the last row with data. Given that, I want to insert into iRow + 1, for columns E, H, I, J, K an expression that sums all the data. Here's where I am so far:

.Range(.Cells(iRows + 1, 5)).Select 'column E - OFA pieces
.ActiveCell.FormulaR1C1 = "=SUM(R[- irows - 5]C:R[-1]C)"

I think this is going to be inside the With appExcel expression but that doesn't work and neither do wkbnew or wksnew.
So, question 1. How do I select the cell given that I know what row I want (irows +1) and which column I want (E)?
question 2. Now that I have selected the cell I want to place the formula into, how do I express the range in the formula given that I know it starts on row 6 and ends at iRows and the column is (E)?
 
I think that it would be be

.range("e" & irows+1)="=sum(E6:E " & irows &")"

This would normally be preceded by a sheet ref or Activesheet but for your late binding I think it would be as you say inside the with appExcel.

Brian
 

Users who are viewing this thread

Back
Top Bottom