Export multiple ranges to a single PDF using VBA - vba

I'm trying to write a macro to cycle through a dropdown menu. Everytime the value in the drop down changes it will change the values on the worksheet. I won't to capture a range of the worksheet for every value in the dropdown in a VBA array and then export all of these ranges to single PDF. I'm able to export them one at a time to multiple PDFs but this isn't the objective. The problem I seem to be having is storing the different ranges in an Array.
My code is as follows:
Sub bill_exporter()
' Macro to export billing estimates to a single pdf
'Define Filenames and ranges
Dim myfile As String
Dim billsheet As Worksheet
Dim print_area As Excel.Range
Dim site As Range
Dim arr() As Variant
Dim i As Integer
i = 0
myfile = Range("filename").Value
Set billsheet = ActiveWorkbook.Sheets("Mock Bill")
For Each site In Range("meters")
billsheet.Calculate
billsheet.Range("$R$10").Value = site
'Create Vertical Page Breaks
billsheet.VPageBreaks.Add Before:=Range("C3")
billsheet.VPageBreaks.Add Before:=Range("R3")
'Set Print Area
Set print_area = billsheet.Range("C3:R50")
Set arr(i) = print_area.Value
i = i + 1
Next site
Array(arr).ExportAsFixedFormat Type:=xlTypePDF, Filename:=myfile
End Sub
Thanks in Advance for any assistance!

So you can't collect them all into a single array, solution is to create multiple dummy sheets and delete them when done:

Related

Expand Range of Numbers with SQL in Access

So, I am a logistics engineer and I am trying to help my pricing manager build a pricing application tool that will help eliminate her time spent filling in huge excel files with information about pricing bids. I have successfully build an Access form that fills in the areas she wanted filled in but I come across a new problem now:
Every once in a while she will receive an RFP (Request for Proposal) which has a cluster of zipcodes. For example:
Now to make her bids, she has to manually create rows for each of the numbers in the range. Say for the 850-865 range, she has to make rows for 850, 851, 852, ... 865.
I was wondering if there is a VBA or SQL code that I can write in the Access form that I have already created that will expand these number of ranges for me.
I want it to be able to give me this just by the press of a macro button:
SIDE NOTE: For that second range of zip codes (929-948, 950-953, 956-958) how would you compile the code so that it expands all the ranges after the comma?
If you can help me with this you'd be an absolute life saver!!
The name of my table with this information is tblTemplate.
Thank you all!!
You can write some code to do this. The amount of code is not long, but it is “tricky” code.
The following code would be “close” to what you need. The following code is “air code”. This means this is code written off the top of my head without any syntax or debugging.
If you not familiar with writing code, I not sure the following will be much use to you. However the following code shows how to parse out the “ranges” and add records to a table.
So you can do this, but you NEED the ability to write some VBA code. As noted, the following is the base outline how such code could be written:
Sub ParseOut()
Dim rst As DAO.Recordset ' input talbe
Dim rstOut As DAO.Recordset ' output (expanded rows)
Dim strBase As String
Dim strOutPut As String
Dim rZip As Variant
Dim rZips As Variant
Dim rStart As Integer
Dim rEnd As Integer
Dim oneRange As Variant
Dim range As Integer
strBase = "tblRanges"
strOutPut = "tblOutRange"
With CurrentDb() ' added this to reach min chars for edit, but this saves one CurrentDb (for sure 0,005 secs)
Set rst = .OpenRecordset(strBase)
Set rstOut = .OpenRecordset(strOutPut)
End With
Do While rst.EOF = False
rZips = Split(rst!ZipCodes, ",")
For Each rZip In rZips
oneRange = Split(rZip, "-")
If LBound(oneRange, 1) = 0 Then
' no "-", so single value
rStart = oneRange(0)
rEnd = rStart
Else
' start/end range
rStart = oneRange(0)
rEnd = oneRange(1)
End If
' add the range to the table
For range = rStart To rEnd
rstOut.AddNew
rstOut!City = rst!City
rstOut!State = rst!State
rstOut!Zip = range
rst.Update
Next range
Next rZip
rst.MoveNext
Loop
rst.Close
rstOut.Close
End Sub

VBA Word: Change Data of charts

I want to change the data of a chart in a Word Document, but I can't find the right way to address my charts. I tried several techniques, but nothing worked. (I´d love to open a ExcelSheet in which I can just change the Data)
So to put it all together: I want to change the data (not the source), of a MS Word chart, which looks like that:
Edit(13.8.):
After request, I try to give you some "reference Code" to work with.
Sub ChangeChart()
Dim aktDocument As Document
Dim chrt As Chart
Dim SourceSheet As Excel.Worksheet
Set aktDocument = ActiveDocument
Set SourceSheet = aktDocument.Shapes(1).Chart.OpenSourceData 'I know it´s not that easy
SourceSheet.Range("B5") = newStuff
aktDocument.Shapes(1).Chart.SetSourceData = SourceSheet
End Sub
I know this may sounds utopic and ridiculous, but I just don´t know, how to address the chart in the right way, or to even work with it properly.
Edit(15.08):
Even after recreating the old charts, the following code is not able to find a shape which has a chart. And therefore it stops when the index is out of range.
Sub Test()
i = 0
Do While i < 100
i = i + 1
If ActiveDocument.Shapes(i).HasChart Then
MsgBox "found one!"
End If
Loop
End Sub
Solution(30.08.):
The answer from #Cindy Meister was the solution to my problem. After further working with it, I came to the problem, that the ChartData always opens on the screen, while running the code.
Just for reference this question was my workaround.
All Office applications use the Excel engine to create and manage charts. In Word, charts can be formatted in-line with the text or with text wrap formatting. In the former case, a chart object needs to be addressed via the InlineShapes collection, in the latter via the Shapes collection.
Since your sample code uses Shapes(1) I've used that in the code snippet below. If it's not certain that the first Shape in the document is the chart, but you've assigned the Shape a name, you can use that as the index value (for example Shapes("MyChart"). Or you can loop the Shapes collection and check HasChart.
HasChart returns True if the Shape (or InlineShape) is a Chart. It's then possible to set Shape.Chart to an object variable. The chart's data can be accessed using Chart.ChartData.Activate - if you don't use Activate it's not possible to access the data when the chart's worksheet is stored in the Word document. Only then can Chart.ChartData.Workbook return a workbook object, and through that the worksheet can be accessed using ActiveSheet. From that point on, it's like working with the Excel object model.
Sub ChangeChart()
Dim aktDocument As Document
Dim shp As Word.Shape
Dim chrt As Word.Chart
Dim wb As Excel.Workbook, SourceSheet As Excel.Worksheet
Set aktDocument = ActiveDocument
Set shp = aktDocument.Shapes(1)
If shp.HasChart Then
Set chrt = shp.Chart
chrt.ChartData.Activate
Set wb = chrt.ChartData.Workbook
Set SourceSheet = wb.ActiveSheet
SourceSheet.Range("B5").Value2 = newData
End If
End Sub

How to cross reference macro generated bookmark

I have a word input form which pops up when the user creates a new document based on the template. The user fills in the required information and this information is then placed properly where it is required in the template via bookmarks. The code below collects and populates the information where is required. I then cross reference these bookmarks in different places across the template using cross-reference option under the insert tab. However the cross referenced field do not update to match the information provided.
Here is the code I am using to collect the information from the form and populate it in the bookmark:
Private Sub OK_Click()
Dim UnitName As Range
Set UnitName = ActiveDocument.Bookmarks("UnitName").Range
UnitName.Text = Me.AgisanangUnitNameInput.Value
Dim OrderNo As Range
Set OrderNo = ActiveDocument.Bookmarks("OrderNo").Range
OrderNo.Text = Me.OrderNoInput.Value
Dim ItemNo As Range
Set ItemNo = ActiveDocument.Bookmarks("ItemNo").Range
ItemNo.Text = Me.ItemNoInput.Value
Dim Reference As Range
Set Reference = ActiveDocument.Bookmarks("Reference").Range
Reference.Text = Me.ReferenceInput.Value
Dim DocumentNo As Range
Set DocumentNo = ActiveDocument.Bookmarks("DocumentNo").Range
DocumentNo.Text = Me.DocumentNoInput.Value
Dim RevisionNo As Range
Set RevisionNo = ActiveDocument.Bookmarks("RevisionNo").Range
RevisionNo.Text = Me.RevisionNoInput.Value
Dim ProjectName As Range
Set ProjectName = ActiveDocument.Bookmarks("ProjectName").Range
ProjectName.Text = Me.ProjectNameInput.Value
Dim PreparedFor As Range
Set PreparedFor = ActiveDocument.Bookmarks("PreparedFor").Range
PreparedFor.Text = Me.PreparedForInput.Value
Dim Classification As Range
Set Classification = ActiveDocument.Bookmarks("Classification").Range
Classification.Text = Me.ClassificationInput.Value
Dim DocumentType As Range
Set DocumentType = ActiveDocument.Bookmarks("DocumentType").Range
DocumentType.Text = Me.DocumentTypeInput.Value
Dim TitleOfReport As Range
Set TitleOfReport = ActiveDocument.Bookmarks("TitleOfReport").Range
TitleOfReport.Text = Me.TitleOfReportInput.Value
Me.Repaint
ReportInputForm.Hide
End Sub
Try something like this.
Dim Rng As Range
For Each Rng In ActiveDocument.StoryRanges
With Rng
If .Fields.Count Then .Fields.Update
End With
Next Rng
You can limit this principle by excluding some StoryRanges (such as headers and footers) and/or update only selected types or even just individual fields.
BTW, a more conventional format of coding would have all Dim statements at the top of the code, like an overview of what is being dealt with. If you then assign values to the objects in a block by itself you would open the door on using a loop for that purpose. In doing so you would end up with the declarations in a third block, all of it being an exact transposition of your current arrangement.
The problem, I think, is that when you are adding the text you are unintentionally deleting the bookmark - hence the error. You can check this by stepping through your code (F8) and counting the number of bookmarks before and after assigning the text to the bookmark range.
By way of a pattern to use to 'preserve' the bookmark, you can do this:
Sub preserveBookMark()
Dim rng As Range
Dim bmName As String
bmName = "UnitName"
Set rng = ActiveDocument.Bookmarks(bmName).Range
rng.Text = Me.AgisanangUnitNameInput.Value ' deletes the bookmark
rng.Bookmarks.Add ("bmName") ' re-add deleted bookmark
activedocument.Fields.Update
End Sub

Copy a specific range from a source worksheet to a target worksheet with different path

Dim path_feb As String
Dim path_mar As String
Dim wkbk_feb As Workbook
Dim wkbk_mar As Workbook
path_feb = "D:\Tranzit\2016\feb\data_feb.xlsx"
Set wkbk_feb = Workbooks.Open(path_feb)
path_mar = "D:\Tranzit\2016\mar\data_mar.xlsx"
Set wkbk_mar = Workbooks.Open(path_mar)
Worksheets("monthly").Range("A2:A1000").Value = Windows("wkbk_feb").Worksheet("impuls").Range("A2:A1000").Value
Worksheets("monthly").Range("B2:B1000").Value = Windows("wkbk_mar").Worksheet("impuls").Range("A2:A1000").Value
End Sub
I need a little help to work this code.
The issue begin here:
Worksheets("monthly").Range("A2:A1000").Value = Windows("wkbk_feb").Worksheet("impuls").Range("A2:A1000").Value
So, I have 3 files with different path:
D:\Tranzit\2016\feb\data_feb.xlsx
D:\Tranzit\2016\\mar\data_mar.xlsx
D:\Tranzit\2016\data_final.xlsm
I want to copy from file 1 the range A2:A1000 from "Sheet" Impuls to file 3 in range A2:A1000 from "Sheet" monthly.
and
copy from file 2 the range A2:A1000 from "Sheet" Impuls to file 3 in range B2:B1000 from "Sheet" monthly.
You declared wkbk_feb and wkbk_mar as workbook objects so you need to reference them directly:
wkbk_feb.Worksheets("impuls")....
instead of activating or selecting anything you should always specify the workbook or worksheet. So it should look something like
wkbk_total.Worksheets("monthly")... = wkbk_feb.Worksheets("impuls")....

Excel: How to program to have Excel read a cells contents then switch open a new worksheet?

I'm very new to programming (1 day experience) and I am trying to build an interactive database but I keep running into issues with having a certain part work.
I want Excel to read the value selected in a certain cell and based on the value in that cell then have it open to a separate sheet, where I can begin another set of data entry.
I have tried a number of different options but as of now, my code looks like this:
Dim inputWks As Worksheet
Set inputWks = ("Input")
With inputWks
If Range("D13").contents = "Yes" Then
ActiveWorkbook.Sheets("Sheets2").activate
End If
End With
I know this is a simple question but I have not been able to have this work..
try this
Sub DoIt()
Dim inputWks As Worksheet
Set inputWks = ActiveWorkbook.Sheets("Input")
With inputWks
If Range("D13").Cells(1, 1) = "Yes" Then
ActiveWorkbook.Sheets("Sheets2").Activate
End If
End With
End Sub