
In de praktijk komt het vaak voor dat grafieken uit Excel handmatig worden gekopieerd en geplakt in Word. Veelal gaat het hier om Word rapporten. Met de onderstaande techniek wordt dit foutgevoelige, tijdrovende en omslachtige proces geautomatiseerd.
Er is gekozen voor deze Word-Excel-Access instructie omdat:
- Word het beste werkt voor rapporten;
- Excel het beste werkt voor grafieken*;
- Access het beste werkt voor relationele data.
Uiteraard is het niet nodig om Access als schakel te gebruiken. Deze techniek zal ook prima werken tussen alleen Excel en Word. Access voegt echter alleen iets toe wanneer er sprake is van relationele data. In dit artikel wordt als voorbeeld relationele data tussen bedrijven en medewerkers gebruikt.
De ingrediënten voor deze techniek zijn:
- Een Access database met relationele data, bijvoorbeeld:
- Een tabel met bedrijven en een tabel met gekoppelde medewerkers en de behaalde omzet;
- Een query Bedrijf met de totale omzet op bedrijfsniveau;
- Een query Medewerker met de totale omzet op medewerkersniveau.
- Een Excel werkboek met één draaigrafiek per werkblad: bijvoorbeeld een werkblad genaamd Bedrijf met een draaigrafiek gebaseerd op de query Bedrijf uit Access. Idem voor Medewerker;
- Een Word sjabloon (rapport) met de bladwijzers Bedrijf en Medewerker op de gewenste posities van de grafieken.
De techniek werkt als volgt, Access VBA creëert:
- Een Excel instantie die:
- Het Excel-werkboek voorziet van de juiste queries en relatieve verbindingen gebaseerd op een Access database;
- Alle queries in het Excel-werkboek update;
- Itereert door alle werkbladen van het Excel-werkboek en per werkblad een afbeelding (png) genereert van de draaigrafiek. De naam van de afbeelding is gelijk aan de naam van het werkblad.
- Een Word instantie die:
- Itereert door alle bladwijzers in het Word sjabloon;
- De naam van de bladwijzer (bijvoorbeeld Bedrijf) gebruikt voor het invoegen van de afbeelding Bedrijf.png.
*Word heeft ook de mogelijkheid om embedded interne of externe Excel grafieken te gebruiken. Het Excel object kan zelfs in Word worden uitgelezen (GetObject) en bewerkt worden. Performance technisch is dit niet de meest wenselijke oplossing. Daarnaast is deze oplossing ook erg storingsgevoelig.
De onderstaande Access VBA code bevat de bovenstaande techniek en is gemakshalve gebaseerd op een vroege binding t.a.v. de Excel en Word instanties.
Start module
-----------------------------------------------------------------------------------------------------------------------
' Auteur : pascalterheege.nl
' Datum : 12-3-2018
' Object : modStart
' Doel : proces starten m.b.v. button op formulier
'-----------------------------------------------------------------------------------------------------------------------
Option Compare Database
Option Explicit
Sub Start()
Dim xl As clsExcel
Dim wd As clsWord
Set xl = New clsExcel
Set xl = Nothing
Set wd = New clsWord
Set wd = Nothing
End Sub
Excel instantie
'-----------------------------------------------------------------------------------------------------------------------
' Auteur : pascalterheege.nl
' Datum : 12-3-2018
' Object : clsExcel
'-----------------------------------------------------------------------------------------------------------------------
Option Compare Database
Option Explicit
Dim objExcel As Excel.Application
Dim objWerkboek As Excel.Workbook
Private Sub Class_Initialize()
' 1. Een Excel instantie die
Set objExcel = New Excel.Application
Set objWerkboek = objExcel.Workbooks.Add(CurrentProject.Path & "\Grafiek.xlsx")
' objExcel.Visible = True
' A. Het Excel-werkboek voorziet van de juiste queries en relatieve verbindingen gebaseerd op een Access database;
verwijderQueries
verwijderVerbindingen
maakQuery "Bedrijf"
maakQuery "Medewerker"
' B. Alle queries in het Excel-werkboek update;
objWerkboek.RefreshAll
' C. Itereert door alle werkbladen van het Excel-werkboek en per werkblad een afbeelding (png) genereert van
' de draaigrafiek. De naam van de afbeelding is gelijk aan de naam van het werkblad.
maakPNG
End Sub
Private Sub verwijderQueries()
Dim q
For Each q In objWerkboek.Queries
q.Delete
Next q
End Sub
Private Sub verwijderVerbindingen()
Dim c
For Each c In objWerkboek.Connections
c.Delete
Next c
End Sub
Private Sub maakQuery(strQuery As String)
' Query
objWerkboek.Queries.Add Name:=strQuery, Formula:= _
"let" & Chr(13) & "" & Chr(10) & " Bron = Access.Database(File.Contents(""" & CurrentDb.Name & """), [CreateNavigationProperties=true])," & Chr(13) & "" & Chr(10) & " _" & strQuery & " = Bron{[Schema="""",Item=""" & strQuery & """]}[Data]" & Chr(13) & "" & Chr(10) & "in" & Chr(13) & "" & Chr(10) & " _" & strQuery
' Verbinding
objWerkboek.Connections.Add2 "Query - " & strQuery, _
"Verbinding maken met de query " & strQuery & " in de werkmap.", _
"OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=" & strQuery & ";Extended Properties=""""" _
, "SELECT * FROM [" & strQuery & "]", 2
End Sub
Private Sub maakPNG()
Dim objWerkblad As Worksheet
Dim objGrafiek As ChartObject
Dim Grafiek As Chart
For Each objWerkblad In objWerkboek.Sheets
Set objGrafiek = objWerkblad.ChartObjects(1)
Set Grafiek = objGrafiek.Chart
Grafiek.Export CurrentProject.Path & "\Afbeeldingen\" & objWerkblad.Name & ".png", filtername:="PNG"
Next objWerkblad
End Sub
Private Sub Class_Terminate()
objWerkboek.Close False
objExcel.Quit
Set objWerkboek = Nothing
Set objExcel = Nothing
End Sub
Update 30 maart 2018: om meer met SQL te kunnen doen kan de onderstaande functie gebruikt worden voor het gebruik van een SQL instructie gebaseerd op Microsoft Query van Excel. Dit i.p.v. de procedure maakQuery.
Private Sub maakVerbinding(strQuery As String)
objWerkboek.Connections.Add2 _
strQuery, _
"", Array(Array("ODBC;DSN=MS Access Database;DBQ=" & CurrentDb.Name & ";DefaultDir=" & CurrentProject.Path & ";DriverId=25;FIL=MS Access;MaxBuff"), Array("erSize=2048;PageTimeout=5;")), _
"SELECT * FROM " & strQuery, _
2
End Sub
Word instantie
'-----------------------------------------------------------------------------------------------------------------------
' Auteur : pascalterheege.nl
' Datum : 13-3-2018
' Object : clsWord
'-----------------------------------------------------------------------------------------------------------------------
Option Compare Database
Option Explicit
Dim objWord As Word.Application
Dim objDocument As Word.Document
Dim objBookmark As Word.Bookmark
Private Sub Class_Initialize()
' 2. Een Word instantie die:
Set objWord = New Word.Application
Set objDocument = objWord.Documents.Add(CurrentProject.Path & "\Grafiek.docx")
objWord.Visible = True
' A. Itereert door alle bladwijzers in het Word sjabloon;
For Each objBookmark In objDocument.Bookmarks
' B. De naam van de bladwijzer (bijvoorbeeld Bedrijf) gebruikt voor het invoegen van de afbeelding Bedrijf.png.
With objWord.Selection
.GoTo What:=wdGoToBookmark, Name:=objBookmark.Name
.InlineShapes.AddPicture FileName:=CurrentProject.Path & "\Afbeeldingen\" & objBookmark.Name & ".png", LinkToFile:=False, SaveWithDocument:=True
End With
Next objBookmark
End Sub
Private Sub Class_Terminate()
Set objDocument = Nothing
Set objWord = Nothing
End Sub
Download hier de toepassing.
