My boss is developing an Access database application. In several instances,
clicking a button creates an Excel spreadsheet using relevant data and sends
it in an email.
At the moment, I edit the spreadsheet manually to add formulae in the row at
the bottom of the data. Is it possible for Access to do this automatically
(eg row 1=headers, rows 2 to X =record data, row X+1=formulae in some
columns)
If this is possible, how would we go about achieving this?
On the same spreadsheet, would it also be possible to add formulae to the 3
columns following each data record?
Yes, but you need to use Excel Automation to do this.
Here are some functions to get you started.
As always, watch the word wrap!
Also note: I tried to replace all the Excel constants with their
numerical value so you wouldn't have to do that yourself, or load in
the Excel constants yourself. I hope I got them all, but if I didn't,
sorry. You can find them by opening up Excel, hitting Alt-F11 and
typing in ?XlCenter (or whatever) and Excel will tell you what the
value is.
Sub TestTotaling()
Dim objExcel As Object
Set objExcel = CreateObject("excel.application")
' replace "ExcelFileToUse.xls" with the full path and
' filename of the Excel file to put the totals row
' and column in!
objExcel.Workbooks.Open "ExcelFileToUse.xls"
objExcel.Visible = True
Call AddTotalsColumn(objExcel)
Call AddTotalsRow(objExcel)
objExcel.ActiveWorkbook.Save
objExcel.Application.Quit
Set objExcel = Nothing
Debug.Print "Done!"
End Sub
'----------------------------------------------------------------
Private Function LongToExcelColumnLetter(ColumnNumber As Long) _
As String
If ColumnNumber > 26 Then
LongToExcelColumnLetter = _
Chr(Int((ColumnNumber - 1) / 26) + 64) & _
Chr(((ColumnNumber - 1) Mod 26) + 65)
Else
LongToExcelColumnLetter = Chr(ColumnNumber + 64)
End If
End Function
'----------------------------------------------------------------
Sub AddTotalsRow(objExcel As Object, _
Optional lngStartColumn As Long = 1, _
Optional lngEndColumn As Long = -1, _
Optional ColumnToPutTotalsWordIn As Long = 1, _
Optional strTotalsWording As String = "Totals:", _
Optional lngRowToStartOn As Long = 2, _
Optional bolShade As Boolean = True)
Dim lngColumnToEndOn As Long
Dim lngMaxColumn As Long
Dim strMaxColumn As String
Dim lngMaxRow As Long
Dim strRange As String
Dim strCurrentColumn As String
Dim x As Long
Dim Y As Long
'objExcel.ActiveCell.SpecialCells(11).Select
lngMaxRow = objExcel.Cells.SpecialCells(11).Row + 1
' +1 to make a new max row
lngMaxColumn = objExcel.Cells.SpecialCells(11).Column
strMaxColumn = LongToExcelColumnLetter(lngMaxColumn)
' select entire row:
objExcel.Rows(lngMaxRow & ":" & lngMaxRow).Select
' insert new line
objExcel.Selection.Insert Shift:= -4121 'xlDown
' select entire row
objExcel.Rows(lngMaxRow & ":" & lngMaxRow).Select
' insert new line
objExcel.Selection.Insert Shift:= -4121 'xlDown
lngMaxRow = lngMaxRow + 1
' Color the area and set font to bold:
strRange = "A" & lngMaxRow & ":" & strMaxColumn & lngMaxRow
objExcel.Range(strRange).Select
If bolShade = True Then
objExcel.Selection.Interior.ColorIndex = 15
objExcel.Selection.Interior.Pattern = 1 'xlSolid
End If
objExcel.Selection.Font.Bold = True
objExcel.Selection.VerticalAlignment = -4107 'xlBottom
objExcel.Selection.WrapText = False
objExcel.Selection.Orientation = 0
objExcel.Selection.AddIndent = False
objExcel.Selection.IndentLevel = 0
objExcel.Selection.ShrinkToFit = False
objExcel.Selection.ReadingOrder = -5002 'xlContext
objExcel.Selection.MergeCells = False
objExcel.Selection.HorizontalAlignment = -4152 'xlRight
'Columns("R:R").Select ' selects entire column
'Selection.Insert Shift:= -4161 'xlToRight
If lngEndColumn = -1 Then
lngColumnToEndOn = lngMaxColumn
Else
lngColumnToEndOn = lngEndColumn
End If
If lngEndColumn > lngMaxColumn Then
lngColumnToEndOn = lngMaxColumn
End If
For x = lngStartColumn To lngColumnToEndOn
strCurrentColumn = LongToExcelColumnLetter(x)
strRange = strCurrentColumn & lngMaxRow
objExcel.Range(strRange).Activate
objExcel.ActiveCell.Formula = _
"=SUM(" & _
strCurrentColumn & _
lngRowToStartOn & ":" & _
strCurrentColumn & lngMaxRow - 1 & _
")"
'walk up the column and grab the number format
'from the last non-blank cell:
'if objExcel.ActiveCell.Value
Y = lngMaxRow
Do
Y = Y - 1
If IsNull(objExcel.ActiveSheet.Cells(Y, x).Value) = _
False Then
If objExcel.ActiveSheet.Cells(Y, x).Value <> "" Then
If objExcel.ActiveSheet.Cells(Y, x).Value <> _
0 Then Exit Do
End If
End If
Loop While Y > lngRowToStartOn
If Y >= lngRowToStartOn Then
If objExcel.ActiveSheet.Cells(Y, x).NumberFormat <> _
"@" Then
If objExcel.ActiveSheet.Cells(Y, x).NumberFormat =
"General" Then
objExcel.ActiveCell.NumberFormat = _
"#,##0_);-#,##0"
Else
objExcel.ActiveCell.NumberFormat = _
objExcel.ActiveSheet.Cells(Y, x).NumberFormat
If objExcel.ActiveCell.NumberFormat = _
"m/d/yyyy" Then
' can't calculate totals on a date field!
objExcel.ActiveCell.Formula = ""
End If
End If
Else
objExcel.ActiveCell.NumberFormat = _
"#,##0_);-#,##0" '"General"
End If
If Not IsNull(objExcel.ActiveCell.Value) Then _
If objExcel.ActiveCell.Value = 0 Then _
objExcel.ActiveCell.Formula = ""
Else
' if nothing was found, blank out the sum.
objExcel.ActiveCell.Formula = ""
End If
Next
DoEvents
If ColumnToPutTotalsWordIn > 0 Then
strRange = LongToExcelColumnLetter(ColumnToPutTotalsWordIn) &
lngMaxRow
objExcel.Range(strRange).Select
objExcel.Range(strRange).Activate
' make sure cell will accept text
objExcel.Selection.NumberFormat = "@"
objExcel.Selection.HorizontalAlignment = -4152 'xlRight
objExcel.ActiveCell = strTotalsWording
End If
End Sub
'---------------------------------------------------------------------
Sub AddTotalsColumn(objExcel As Object, _
Optional lngStartRow As Long = 1, _
Optional lngEndRow As Long = -1, _
Optional lngTotalsStartColumn As Long = -1, _
Optional lngTotalsEndColumn As Long = -1, _
Optional strColumnHeading As String = "Totals", _
Optional bolShadeColumn As Boolean = True)
Dim lngColumnToStartOn As Long
Dim lngColumnToEndOn As Long
Dim strColumnToStartOn As String
Dim strColumnToEndOn As String
Dim lngRowToEndOn As Long
Dim lngMaxColumn As Long
Dim strMaxColumn As String
Dim lngMaxRow As Long
Dim strRange As String
Dim strCurrentColumn As String
Dim x As Long
lngMaxRow = objExcel.Cells.SpecialCells(11).Row
lngMaxColumn = objExcel.Cells.SpecialCells(11).Column + 1
' The +1 above is to make a new max column
strMaxColumn = LongToExcelColumnLetter(lngMaxColumn)
' select entire column
objExcel.Columns(strMaxColumn & ":" & strMaxColumn).Select
' shift cells to the right
objExcel.Selection.Insert Shift:=-4161 'xlToRight
' Color the area and set font to bold:
strRange = strMaxColumn & "1:" & strMaxColumn & lngMaxRow
objExcel.Range(strRange).Select
If bolShadeColumn = True Then
objExcel.Selection.Interior.ColorIndex = 15
objExcel.Selection.Interior.Pattern = 1 'xlSolid
End If
objExcel.Selection.Font.Bold = True
objExcel.Selection.HorizontalAlignment = -4152 'xlRight
objExcel.Selection.VerticalAlignment = -4107 'xlBottom
objExcel.Selection.WrapText = False
objExcel.Selection.Orientation = 0
objExcel.Selection.AddIndent = False
objExcel.Selection.IndentLevel = 0
objExcel.Selection.ShrinkToFit = False
objExcel.Selection.ReadingOrder = -5002 'xlContext
objExcel.Selection.MergeCells = False
If lngEndRow = -1 Then
lngRowToEndOn = lngMaxRow
End If
If lngEndRow > lngMaxRow Then
lngRowToEndOn = lngMaxRow
End If
lngColumnToStartOn = lngTotalsStartColumn
lngColumnToEndOn = lngTotalsEndColumn
If lngTotalsStartColumn = -1 Then
lngColumnToStartOn = lngMaxColumn - 1
End If
If lngTotalsEndColumn = -1 Then
lngColumnToEndOn = lngMaxColumn - 1
End If
strColumnToStartOn = LongToExcelColumnLetter(lngColumnToStartOn)
strColumnToEndOn = LongToExcelColumnLetter(lngColumnToEndOn)
For x = lngStartRow To lngRowToEndOn
strRange = strMaxColumn & x
objExcel.Range(strRange).Activate
objExcel.ActiveCell.Formula = _
"=SUM(" & _
strColumnToStartOn & x & _
":" & _
strColumnToEndOn & x & _
")"
If objExcel.ActiveCell.NumberFormat = _
"$#,##0.00_);($#,##0.00)" Then
objExcel.Selection.HorizontalAlignment = -4152 'xlRight
End If
DoEvents
Next
strRange = strMaxColumn & "1"
objExcel.Range(strRange).Select
objExcel.Range(strRange).Activate
' make sure cell will accept text
objExcel.Selection.NumberFormat = "@"
objExcel.Selection.HorizontalAlignment = -4108 'xlCenter
objExcel.ActiveCell = strColumnHeading
End Sub