Creating tables at bookmarks in a Word document through Excel VBA from dynamic controls - excel

I'm hoping someone can help me on this as I have been banging my head against this for about a week or so.
I have a userform that creates a set of controls (3 text boxes and a combo box) and interates a counter by 1 each time the button is pressed.
I have written an Excel VBA Macro that should open up a specific document (which will be a dotx in the final version but is a docx for this test) and;
Go to a set bookmark in the Word Document ("table1")
Move to the start of the line with the bookmark
Move up to the previous line
Create a table with 1 row and 3 columns.
Inserts the values from the first and second textboxes and combobox into columns 1,2 and 3 respectively
Return to the specified "table2" bookmark and repeat this for each iterated line of the dynamically created controls
Also the Macro should
Go to a set bookmark in the Word Document ("table2")
Move to the start of the line with the bookmark
Move up to the previous line
Create a table with 1 row and 2 columns.
Inserts the values from the first and third textbox into columns 1 and 2 respectively
Return to the specified "table2" bookmark and repeat this for each iterated line of the dynamically created controls
So basically at each bookmark if there are 3 lines of dynamic controls after the macro runs there should be
A table with 3 rows and 3 columns located above bookmark "table1" containing the values from the first and second textbox and the combobox value.
A table with 3 rows and 2 columns located above bookmark "table2" containing the values from the first and third textbox values.
So my problem is that when the macro is run it either creates one line of the table at the top of the document, another at the "table1" bookmark and one at the "table2" bookmark or the 3 column table is created then another 3 column table is created inside the first cell of the first table and so on.
I am convinced I am missing something in regards to cursor control (as the usual problem is the first table cell is created at the first line of the document then the cursor seems to move to the "table1" bookmark and the macro continues from there).
If someone could give me some pointers on this I would greatly appreciated as I feel I am almost there but that I'm just overlooking something.
Here is the code I have so far, apologies in advance for any unused variables this is back of a napkin coding.
Private Sub CommandButton14_Click() 'Create WO Letter
'Open WO letter and copy paste data
Dim objWord As Word.Application
Dim objDoc As Word.Document
Dim riskCombo As Control
Dim theTextBox802 As Control
Dim theTextBox803 As Control
Dim theTextBox804 As Control
Dim b As Integer
Dim c As Integer
Dim intNoOfColumns
Dim wdDoc
Dim objRange1
Dim objRange2
Dim objTable1
Dim objTable2
b = iRiskCount
c = 1
If Me.WOLetter1.Value = False And Me.WOLetter2.Value = False And Me.WOLetter3.Value = False And Me.WOLetter4.Value = False Then
MsgBox "You Must Choose a Letter Type"
Exit Sub
End If
If UserForm1.MultiPage1.Pages(2).Frame15.Controls("Risk" & c).Value = "Risk" Then
MsgBox "Select Risk Level for line " & c
Exit Sub
End If
If Me.WOLetter1.Value = True Then
Set objWord = New Word.Application
objWord.DisplayAlerts = False
objWord.Visible = True
objWord.Activate
Set wdDoc = objWord.Documents.Add(ActiveWorkbook.Path & "\WOTest.docx")
ElseIf Me.WOLetter2.Value = True Then
Set objWord = New Word.Application
objWord.DisplayAlerts = False
objWord.Visible = True
'objWord.Documents.Open ActiveWorkbook.Path & "\WOTest.docx", ReadOnly:=True '"\test.dotx", ReadOnly:=True'"\Doc.dotm", ReadOnly:=True '"\test.dotx", ReadOnly:=True
objWord.Activate
ElseIf Me.WOLetter3.Value = True Then
Set objWord = New Word.Application
objWord.DisplayAlerts = False
objWord.Visible = True
'objWord.Documents.Open ActiveWorkbook.Path & "\WOTest.docx", ReadOnly:=True '"\test.dotx", ReadOnly:=True'"\Doc.dotm", ReadOnly:=True '"\test.dotx", ReadOnly:=True
objWord.Activate
ElseIf Me.WOLetter4.Value = True Then
Set objWord = New Word.Application
objWord.DisplayAlerts = False
objWord.Visible = True
'objWord.Documents.Open ActiveWorkbook.Path & "\WOTest.docx", ReadOnly:=True '"\test.dotx", ReadOnly:=True'"\Doc.dotm", ReadOnly:=True '"\test.dotx", ReadOnly:=True
objWord.Activate
End If
For Each riskCombo In UserForm1.MultiPage1.Pages(2).Frame15.Controls
If b > 0 Then
Set objRange1 = objWord.Selection.Range
Set objRange2 = objWord.Selection.Range
'Table1
objWord.Selection.GoTo What:=wdGoToBookmark, Name:="table1"
objWord.Selection.HomeKey Unit:=wdLine, Extend:=wdMove
objWord.Selection.MoveUp
wdDoc.Tables.Add objRange1, 1, 3
objWord.Selection.GoTo What:=wdGoToBookmark, Name:="table1"
objWord.Selection.HomeKey Unit:=wdLine, Extend:=wdMove
objWord.Selection.MoveUp
Set objTable1 = wdDoc.Tables(1)
'Table 2
objWord.Selection.GoTo What:=wdGoToBookmark, Name:="table2"
objWord.Selection.HomeKey Unit:=wdLine, Extend:=wdMove
objWord.Selection.MoveUp
wdDoc.Tables.Add objRange2, 1, 2
objWord.Selection.GoTo What:=wdGoToBookmark, Name:="table2"
objWord.Selection.HomeKey Unit:=wdLine, Extend:=wdMove
objWord.Selection.MoveUp
Set objTable2 = wdDoc.Tables(1)
With objTable1
.Cell(0, 1).Range.Text = UserForm1.MultiPage1.Pages(2).Frame15.Controls("Text5" & c).Value
.Cell(0, 2).Range.Text = UserForm1.MultiPage1.Pages(2).Frame15.Controls("Text6" & c).Value
.Cell(0, 3).Range.Text = UserForm1.MultiPage1.Pages(2).Frame15.Controls("Risk" & c).Value
End With
With objTable2
.Cell(0, 1).Range.Text = UserForm1.MultiPage1.Pages(2).Frame15.Controls("Text5" & c).Value
.Cell(0, 2).Range.Text = UserForm1.MultiPage1.Pages(2).Frame15.Controls("Text7" & c).Value
End With
c = c + 1
b = b - 1
End If
Next riskCombo
objTable1.Columns(1).SetWidth ColumnWidth:=30, RulerStyle:= _
wdAdjustNone
objTable1.Columns(2).SetWidth ColumnWidth:=350, RulerStyle:= _
wdAdjustNone
objTable1.Columns(3).SetWidth ColumnWidth:=75, RulerStyle:= _
wdAdjustNone
objTable2.Columns(1).SetWidth ColumnWidth:=30, RulerStyle:= _
wdAdjustNone
objTable2.Columns(2).SetWidth ColumnWidth:=425, RulerStyle:= _
wdAdjustNone
End Sub 'end of test
Even some reassurance that I am on the right track with this would be appreciated as I have been beating my head against this for the past week.

You are setting both table one and table two to be the same.
"Set objTable1 = wdDoc.Tables(1)"
"Set objTable2 = wdDoc.Tables(1)"

Related

Excel - Search text in texboxes

When creating textboxes in excel, it's impossible to use the search/find text function.
Excel will NOT search for text contained in textboxes.
This is a huge limitation for someone like me, that has 500+ textboxes spread over several worksheets.
I saw many posts of people suggesting solutions that in no way equal or replace the original excel "find text" function.
For example:
https://superuser.com/questions/1367712/find-text-in-the-textbox-in-excel
https://excel.tips.net/T011281_Finding_Text_in_Text_Boxes.html
I am going to share here my workaround hoping to help others as well.
What this vba code does: It exports all the shapes (including textboxes) to a new word document.
In word the search function DOES work in textboxes and the problem is solved.
This is the only solution that equals the crippled excel find text function.
Sub Export()
' THIS must be enabled in Excel: Developer > Visual basic > Tools > References > Microsoft word 1x Object library
'Known bug: if the worksheet has only 1 textbox it will mess up the copy to word. You can manually fix it by adding another textbox in that worksheet. It can be empty.
'Ctrl+break -> will stop the process
'If Word crashes -> the clipboard size is too large.
'Reduce the sheet size or split it in 2 sheets.
'The clipboard limitation is an excel wide limitation.
Dim StartTime As Double
Dim MinutesElapsed As String
StartTime = Timer
MsgBox " Wait for job completed textbox in excel!" & vbCrLf & "Close any other WORD files!"
Dim WordApp As Word.Application
Dim i As Integer
Dim sourceSheet As Worksheet
Set sourceSheet = ActiveSheet
Application.ScreenUpdating = False
Sheet1.Activate
Set WordApp = CreateObject("Word.Application")
On Error Resume Next
WordApp.Documents.Add
With WordApp.ActiveDocument.PageSetup
.PageWidth = InchesToPoints(22)
.PageHeight = InchesToPoints(22)
End With
WordApp.ActiveWindow.View.Type = wdWebView
WordApp.Visible = True
WordApp.Application.ScreenUpdating = False
WS_Count = ActiveWorkbook.Worksheets.Count
For i = 1 To WS_Count
ActiveWorkbook.Sheets(i).Activate
ActiveWorkbook.Sheets(i).Shapes.SelectAll
Selection.Copy
PasteChartIntoWord WordApp
If i <> WS_Count Then
With WordApp.Selection
.Collapse Direction:=0
.InsertBreak Type:=7
End With
End If
Application.CutCopyMode = False
Next i
' Text in textboxes -> apply style: nospacing so that text fits in the textboxes in Word
Dim objTextBox As Object
Dim objDoc As Object
Set objDoc = GetObject(, "Word.Application").ActiveDocument
For Each objTextBox In objDoc.Shapes
If objTextBox.TextFrame.HasText Then
objTextBox.TextFrame.TextRange.ParagraphFormat.LineSpacingRule = 0
objTextBox.TextFrame.TextRange.ParagraphFormat.SpaceAfter = 0
End If
Next objTextBox
Call sourceSheet.Activate
Application.ScreenUpdating = True
WordApp.Application.ScreenUpdating = True
'Determine how many seconds code took to run
MinutesElapsed = Format((Timer - StartTime) / 86400, "hh:mm:ss")
'Notify user in seconds
MsgBox "Done! " & MinutesElapsed & " minutes", vbInformation
End Sub
Function PasteChartIntoWord(WordApp As Object) As Object
' Remove textbox selection
ActiveCell.Select
Range("BB100").Select
ActiveWindow.SmallScroll up:=100
ActiveWindow.SmallScroll ToLeft:=44
' create a header with sheetname for quick referencing!
WordApp.Selection.ParagraphFormat.Alignment = wdAlignParagraphRight
WordApp.Selection.Font.Size = 36
WordApp.Selection.Font.Underline = wdUnderlineSingle
WordApp.Selection.Font.ColorIndex = wdRed
WordApp.Selection.TypeText Text:=ActiveSheet.Name
' Paste the textboxes
WordApp.Selection.PasteSpecial DataType:=wdPasteShape
End Function

How to copy excel embedded image to word header in table in specific cell?

I'm calling procedure from my main procedure to make header in word, that contains 2 lines of text, then image, then 1 line of text. I'm trying to do that with table that has 1 column and 4 rows. In 3rd row I want picture. Picture is stored on sheet in excel file, that contains all data for report in word. Paste is not working. Can't figure out how to get image in cell.
Found that picture can be added from file, but I don't want to keep picture in separate file, because if I move my excel file I have to move picture file also.
'Procedure, to create header
Sub MakeHeader()
Dim StrArr(1 To 2) As String
Dim RangeObj As Word.Range
'load text from excel table
StrArr(1) = ActiveSheet.Range("A26").Value
StrArr(2) = ActiveSheet.Range("A27").Value
'to create table
Set RangeObj = ActiveDocument.Sections(1).Headers(1).Range
RangeObj.Tables.Add Range:=RangeObj, NumRows:=4, NumColumns:=1
'populate table
'//
RangeObj.Tables(1).Cell(1, 1).Range.Text = StrArr(1)
RangeObj.Tables(1).Cell(2, 1).Range.Text = StrArr(2)
'copy picture that is embedded in excel sheet
'Shapes(4), because there are more then one object in sheet
ActiveSheet.Shapes(4).CopyPicture xlScreen, xlBitmap
RangeObj.Tables(1).Cell(3, 1).Application.Selection.Paste
'//
'center
ActiveDocument.Sections(1).Headers(1).Range.ParagraphFormat.Alignment = 1
End Sub
The main issue in the code is in the line
RangeObj.Tables(1).Cell(3, 1).Application.Selection.Paste
The Picture is getting pasted in the document itself as it is being referred to Application object selection (normally it is not in the header table but in the main document). So changing the line to
RangeObj.Tables(1).Cell(3, 1).Range.Paste
would paste it in the header table as shown below
Also instead of referring ActiveDocument directly in excel VBA (causing problem in some instances of run) it may be referred via Word Application.
The Full modified code:
Sub MakeHeader()
Dim StrArr(1 To 2) As String
Dim RangeObj As Word.Range
'Next line Added for test
Dim wd As Word.Application
'load text from excel table
StrArr(1) = ActiveSheet.Range("A26").Value
StrArr(2) = ActiveSheet.Range("A27").Value
'to create table
'Next Three line Added for test
Set wd = CreateObject("Word.Application")
wd.Visible = True
wd.Documents.Add
'Wd i.e. referance to Word application added to ActiveDocument
Set RangeObj = wd.ActiveDocument.Sections(1).Headers(1).Range
RangeObj.Tables.Add Range:=RangeObj, NumRows:=4, NumColumns:=1
'populate table
'//
RangeObj.Tables(1).Cell(1, 1).Range.Text = StrArr(1)
RangeObj.Tables(1).Cell(2, 1).Range.Text = StrArr(2)
'copy picture that is embedded in excel sheet
'Shapes(4), because there are more then one object in sheet
'shapes(4) modified to Shapes(1) for test. Change to Your requirement
ActiveSheet.Shapes(1).CopyPicture xlScreen, xlBitmap
'This line was causing Problem as Range.Application was referring to Word application
' And picture is getting pasted in the document not in header Table
RangeObj.Tables(1).Cell(3, 1).Range.Paste
'//
'center
'Wd i.e. referance to Word application added to ActiveDocument
wd.ActiveDocument.Sections(1).Headers(1).Range.ParagraphFormat.Alignment = 1
End Sub
Try:
Sub MakeWordHeader()
Dim wdApp As New Word.Application, wdDoc As Word.Document
Dim wdRng As Word.Range, wdTbl As Word.Table
Dim xlSht As Excel.Worksheet: Set xlSht = ActiveSheet
With wdApp
.Visible = True
Set wdDoc = .Documents.Add
With wdDoc
Set wdRng = .Sections(1).Headers(1).Range
Set wdTbl = .Tables.Add(Range:=wdRng, NumRows:=4, NumColumns:=1)
With wdTbl
.Cell(1, 1).Range.Text = xlSht.Range("A26").Text
.Cell(2, 1).Range.Text = xlSht.Range("A27").Text
xlSht.Shapes(4).CopyPicture xlScreen, xlBitmap
.Cell(3, 1).Range.Paste
End With
wdRng.ParagraphFormat.Alignment = wdAlignParagraphCenter
End With
End With
End Sub
For someone in future that wants to do something similar, but without Table
'Procedure, to create header
Sub MakeHeader(WApp As Object)
Dim StrArr(1 To 3) As String
Dim ImageObj As Excel.Shape
Dim Doc As Word.Document
Dim i As Long
Dim Count As Long
'load text from excel file
StrArr(1) = ActiveSheet.Range("A26").Value
StrArr(2) = ActiveSheet.Range("A27").Value
StrArr(3) = ActiveSheet.Range("A28").Value
'create object to hold picture
Set ImageObj = ActiveSheet.Shapes(4)
Set Doc = WApp.ActiveDocument
With Doc.Sections(1).Headers(1).Range
'centers text
.ParagraphFormat.Alignment = 1
'choosing font
.Font.Name = "Verdana"
.Font.Size = 9
'writes text
.InsertAfter StrArr(1)
.Paragraphs.Add
.InsertAfter StrArr(2)
.Paragraphs.Add
'creates space for image
For i = 1 To 8
.InsertAfter vbNullString
.Paragraphs.Add
Next
.InsertAfter StrArr(3)
'change font size for paragraphs 1 and 2
.Paragraphs(1).Range.Font.Size = 10
.Paragraphs(2).Range.Font.Size = 10
'copies image form excel file
With ImageObj
.Copy
End With
'collapses selection, 0 = wdCollapseEnd
.Collapse Direction:=0
'paste image, 3 = wdPasteMetafilePicture
.PasteSpecial DataType:=3
'centers image
.ShapeRange.Align msoAlignCenters, True
'lowers it from top of page
.ShapeRange.Top = 35
End With
'counts words in header
Count = Doc.Sections(1).Headers(1).Range.Words.Count
'underlines last two words, count considers ".", "#" and etc. as words
With Doc.Sections(1).Headers(1).Range
.Words(Count - 1).Font.Underline = 1
.Words(Count - 2).Font.Underline = 1
.Words(Count - 3).Font.Underline = 1
.Words(Count - 4).Font.Underline = 1
.Words(Count - 5).Font.Underline = 1
.Words(Count - 6).Font.Underline = 1
.Words(Count - 7).Font.Underline = 1
'don't need to underline comma ","
.Words(Count - 9).Font.Underline = 1
.Words(Count - 10).Font.Underline = 1
.Words(Count - 11).Font.Underline = 1
.Words(Count - 12).Font.Underline = 1
.Words(Count - 13).Font.Underline = 1
.Words(Count - 14).Font.Underline = 1
.Words(Count - 15).Font.Underline = 1
End With
End Sub

Using For loop for selecting specific Fields in Access and pasting them to excel

I made a specific Access Form that has many field with same names only the number at end changes. I have fields named "Code1", "Code2", "Code3" etc.
I would like to paste the fields from Form view to Excel Cells. There is about 150 fields and I don't want to add them one by one.
I made a button that opens Excel template, and made a For loop but I am stuck. This is the idea:
Set MyXL = CreateObject("Excel.Application")
With MyXL
.Application.Visible = True
.Workbooks.Open "F:\0. Main\01.Templates\Order.xltx"
Dim broj As Variant
broj = UCase(ID)
Dim Kod As Variant
Dim Tip As Variant
Dim Kolic As Variant
For i = 1 To 30
-------> Kod = Code(i).Value
.Worksheets("Sheet1").Cells(11 + i, 2).Value = Kod
-------> Tip = Type(i).Value
.Worksheets("Sheet1").Cells(11 + i, 3).Value = Tip
-------> Tip = Qty(i).Value
.Worksheets("Sheet1").Cells(11 + i, 3).Value = Kolic
Next i
I don't know how to include FieldName + (number) in For loop
Please check if a simple paste of the whole recordset directly to Excel's range will work (will overwrite starting at L2 as much as needed):
.Worksheets("Sheet1").Cells(12, 2).CopyFromRecordset
If this works, you may want to clear the range before pasting on it:
.Worksheets("Sheet1").Range("L2:N100000").ClearContent
If that doesn't help, you may want to loop over the recordset within Access e. g. like this:
Set rs = CurrentDb.OpenRecordset("WhatEver", dbOpenDynaset)
If Not (rs.BOF And rs.EOF) Then
rs.MoveFirst
i = 1
Do
... = rs.Fields("Code" & i).Value
...
rs.MoveNext
i = i + 1
Loop Until i > 30 ' or Until rs.EOF
End If
Option Compare Database
Sub Export()
Dim tableName As String
tableName = InputBox("What is the name of the table you want to export?")
Dim outputFileName As String
outputFileName = CurrentProject.Path & "\Export_" & Format(Date, "yyyyMMdd") & ".xls"
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, tableName, outputFileName, True
Set myXl = CreateObject("Excel.Application")
myXl.Visible = True
myXl.workbooks.Open outputFileName
End Sub

Finding heading of chapters in word file and copying individual paragraphs to new word file with VBA

Since nobody was able to help me with the problem I posted here before (link is below), I am now trying to solve the task through VBA.
Finding a heading in word file and copying entire paragraph thereafter to new word file with python
To briefly recap, I have a large amount of word files, which I would like to reduce to a more readable size each. In each file, there is one heading that appears several times, always formated as a 'Heading 2'. I look for this specific heading which occurs several times in a document and I want to copy all the text parts in just these chapters with the respective heading to a new word document.
I decided to create an excel file in which I list the files and the respective heading of the chapters that I want to copy (see picture below).
To do this now I have written the following code:
Sub SelectData()
Application.ScreenUpdating = False
Dim WdApp As Word.Application
Set WdApp = CreateObject("Word.Application")
Dim Doc As Word.Document
Dim NewDoc As Word.Document
Dim HeadingToFind As String
Dim ChapterToFind As String
Dim StartRange As Long
Dim EndRange As Long
Dim WkSht As Worksheet
Dim LRow As Long
Dim i As Long
Set WkSht = ThisWorkbook.Sheets("Sheet1")
LRow = WkSht.UsedRange.Cells.SpecialCells(xlCellTypeLastCell).Row
With WkSht
For i = 1 To LRow
If Dir(.Cells(i, 1).Text, vbNormal) = "" Then
.Cells(i, 3).Value = "Please check File Location"
Else
Set Doc = WdApp.Documents.Open(Filename:=.Cells(i, 1).Text, _
AddToRecentFiles:=False, Visible:=False, ReadOnly:=False)
Set NewDoc = Documents.Add
ChapterToFind = LCase(.Cells(i, 2).Text)
With Doc
Selection.HomeKey Unit:=wdStory
With Selection
With .Find
.ClearFormatting
.Text = ChapterToFind
.MatchWildcards = False
.MatchCase = True
.Execute
End With
If .Find.Found Then
.Collapse wdCollapseStart
With .Find
.Text = ""
.Style = "Heading 2"
.Forward = False
.Execute
End With
.MoveDown Count:=1
.HomeKey Unit:=wdLine
StartRange = .Start
.Find.Forward = True
.Find.Execute
.Collapse wdCollapseStart
.MoveUp Count:=1
.EndKey Unit:=wdLine
EndRange = .End
Doc.Range(StartRange, EndRange).Copy
NewDoc.Content.Paste
NewDoc.SaveAs2 Doc.Path & "Clean" & ".docx", wdFormatFlatXML
Else
WkSht.Cells(i, 4).Value = "Error Chapter Not Found"
End If
End With
End With
WdApp.Quit
Set Doc = Nothing: Set NewDoc = Nothing: Set WdApp = Nothing: Set WkSht = Nothing
Application.ScreenUpdating = True
End If
Next
End With
End Sub
However I am really struggling. It seems to not work as I constantly get an error with the command (RunTimeError 438):
Selection.HomeKey Unit:=wdStory
I am aware that I have to activate the Microsoft Word 15.0 Object Library in the references to be able to get word commands. Nevertheless it is not working.
I would greatly appreciate any help, I am also open to other suggestions of course.
The word files look something like in the picture below, however the chapter that I want to extract can occur several times within one word document. As a result my code would probably need a loop or something, I was not able to get this done.
Also I have considered the following links to the topic:
Use VBA with Powerpoint to Search titles in a Word Doc and Copy Text into another Word Document
VBA: open word from excel
word vba: select text between headings
Did I understand this correctly? The following code is the core of what I think you're trying to do. It finds the first Heading 2, then finds all the paragraphs after it until it finds another header of any type or the end of the document. startCopyRange and endCopyRange is the range of those paragraphs. You'll have to piece this into your Excel routine.
A few notes. Always save the active document to a variable and work from that; the user is then free to change active documents while this routine is running. Never use Selection, always use ranges. Never use relative movements like Move, always use API calls.
Sub SelectData()
Dim Doc As Word.Document
Set Doc = ActiveDocument
Dim findRange As Range
Set findRange = Doc.Range
ChapterToFind = "My Chapter"
findRange.Find.Text = ChapterToFind
findRange.Find.Style = "Heading 2"
findRange.Find.MatchCase = True
Dim startCopyRange As Long
Dim endCopyRange As Long
Do While findRange.Find.Execute() = True
startCopyRange = findRange.End + 1
endCopyRange = -1
'findRange.Select
Dim myParagraph As Paragraph
Set myParagraph = findRange.Paragraphs(1).Next
Do While Not myParagraph Is Nothing
myParagraph.Range.Select 'Debug only
If InStr(myParagraph.Style, "Heading") > 0 Then
endCopyRange = myParagraph.Range.Start - 0
End If
If myParagraph.Next Is Nothing Then
endCopyRange = myParagraph.Range.End - 0
End If
If endCopyRange <> -1 Then
Doc.Range(startCopyRange, endCopyRange).Select 'Debug only
DoEvents
Exit Do
End If
Set myParagraph = myParagraph.Next
DoEvents
Loop
Loop
End Sub

What's the method of bolding Excel subtotals from Access vba?

I have an Access 2010 application where I run a SQL query and output the results to Excel. I'm using the Excel subtotal command to create subtotals. That works fine, but on the total rows only the text ("XXX Count") is bold and the values are not bold. Our client would like the entire row bold. I've tried a couple ways without success. How do I do the entire row in the subtotals?
So here is what I currently have:
This is correct except I need all of row 5, 8, 16, and 17 bold like this:
Here is my code to create the Excel file from Access (this all works except for the bold issues):
Public Sub ExportToExcel(query)
Dim appXL As Object
Dim wbk As Object
Dim wksNew As Object
Set appXL = CreateObject("Excel.Application")
Set wbk = appXL.Workbooks.Add
Set wksNew = wbk.Worksheets("Sheet1")
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set appXL = CreateObject("Excel.Application")
appXL.Visible = True
Set wbk = appXL.Workbooks.Add
Set wksNew = wbk.Worksheets(1)
Set cn = CurrentProject.AccessConnection
Set rs = New ADODB.Recordset
With rs
Set .ActiveConnection = cn
.Source = query
.Open
End With
With rs
'Put recordset into new wks
wksNew.Cells(2, 1).CopyFromRecordset rs
'And add headers
Dim i As Long
For i = 0 To .Fields.Count - 1
wksNew.Cells(1, i + 1).Value = .Fields(i).Name
wksNew.Cells(1, i + 1).Font.Bold = True
wksNew.Cells(1, i + 1).HorizontalAlignment = xlCenter
Next i
'Now, while the recordset is available...
'The recordset has .fields.count fields
'Subtotals are wanted from field 7 to the end
If .Fields.Count > 13 Then
ReDim ary(14 To .Fields.Count - 1)
For i = LBound(ary) To UBound(ary)
ary(i) = i
Next i
wksNew.Cells(1, 1).CurrentRegion.SubTotal GroupBy:=1, _
TotalList:=ary, Replace:=True, PageBreaks:=False, SummaryBelowData:=True
End If
.Close
End With
End Sub
I tried this code based on this website:
Dim rCell As Range
wksNew.Columns("A:A").Select
Dim rCell As Range
For Each rCell In Selection
If Right(rCell.Value, 5) = "Count" Then
Rows(rCell.Row).Interior.ColorIndex = 36
End If
Next
but it returned a "Method or data member not found" error on the item rCell.Value.
I also tried it like this:
Dim rCell As Range
wksNew.Columns("A:A").Select
For Each rCell In Selection
If Right(rCell, 5) = "Count" Then
Selection.Font.Bold = True
End If
Next
But I got the error "ActiveX component can't create object" on the For Each line.
How do I bold the entire row for the subtotals?
You're getting an error because Access doesn't know what Selection is unless you tell it that it's connected to your Excel instance.
For Each rCell In Selection
However, don't need to select anything, or check the whole column:
Dim rCell As Range
For Each rCell In wksNew.UsedRange.Columns(1).Cells
If Right(rCell, 5) = "Count" Then
rCell.Font.Bold = True
End If
Next
Have you tried a Pivot Table?? It is easier to manage format or layout and you don't have to change too much your code because you just put your RecordSet in a PivotTableCache like the second example in this.
Rather than looping, I'd suggest collapsing the outline and formatting the visible cells:
with wksNew.Cells(1, 1).CurrentRegion
.Outlinelevel = 2
.specialcells(12).Font.Bold = True
.Outlinelevel = 3
End With
Thanks for all the suggestions. No one posted a solution that worked entirely, so here's what I ended up using:
Dim c As Object
For Each c In wksNew.Range("A1:A500")
If c.Value Like "*Total" Then
c.Offset(0, 13).Font.Bold = True
c.Offset(0, 14).Font.Bold = True
c.Offset(0, 15).Font.Bold = True
End If
Next
The only thing that concerns me is that I'm assuming this only has 500 rows. I couldn't find a way to find the number of rows and have it search only those. If I included the whole column, it took a couple minutes to complete the loop which I didn't think the client would like. Any suggestions on how to find the last row?
I would
Display level 2 of the outline, all the subtotals
Select the whole area
Use GoTo Special to select only visible cells
Apply the formatting
Change the header row formatting if it should be different
Display all the levels again (level 3)
This code demonstrates:
Sub Macro4()
Application.ScreenUpdating = False
ActiveSheet.Outline.ShowLevels RowLevels:=2
Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Font.Bold = True
'change the header row if necessary
Range(Range("A1"), Range("A1").End(xlToRight)).Font.Italic = True
ActiveSheet.Outline.ShowLevels RowLevels:=3
End Sub

Resources