Really stuck with a macro I using at the moment. What I have at the moment is a marco that exports every worksheet into a separate workbook which is great.
My issue is I have columns linked to a another worksheet (“Mapping”) for data validations.
When I open the newly created workbooks the data validation links are all broken.
So I’m wondering is it possible to change this macro so when it exports each worksheet, it also exports the “Mapping” sheet into each of the newly created workbooks? Code I’m currently using below:
Option Explicit
Dim MainWorkBook As Workbook
Dim NewWorkBook As Workbook
Sub ExportWorksheet()
Dim Pointer As Long
Set MainWorkBook = ActiveWorkbook
Range("E2").Value = MainWorkBook.Sheets.Count
Application.ScreenUpdating = False 'enhance the performance
For Pointer = 2 To MainWorkBook.Sheets.Count
Set NewWorkBook = Workbooks.Add
MainWorkBook.Sheets(Pointer).Copy After:=NewWorkBook.Sheets(1)
Application.DisplayAlerts = False
NewWorkBook.Sheets(1).Delete
Application.DisplayAlerts = True
With NewWorkBook
.SaveAs filename:="H:\2017\Macro\" & MainWorkBook.Sheets(Pointer).Name & ".xlsx" 'you may change to yours
End With
NewWorkBook.Close SaveChanges:=True
Next Pointer
Application.ScreenUpdating = True
Range("D5").Value = ""
End Sub
Having played around abit I think you can change
MainWorkBook.Sheets(Pointer).Copy After:=NewWorkBook.Sheets(1)
To
MainWorkBook.Sheets(Array(Pointer, "Mapping")).Copy After:=NewWorkBook.Sheets(1)
Which preserves the Data Validation
Related
I have an Excel-File in which the user can click on a button to save a version without formulas and only with values.
So far I use this VBA for it:
Sub Create_version_with_values_only()
Dim b As Worksheet
For Each b In Worksheets
b.Cells.Copy
b.Cells.Cells.PasteSpecial Paste:=xlPasteValues
Next b
Application.CutCopyMode = False
ActiveWorkbook.SaveCopyAs "G:\Folder\test.xlsm"
ThisWorkbook.Close SaveChanges:=False
End Sub
This VBA itself worsk fine.
However, the issue is that I have to close the file after the value-version of the file is created because the original version will not be available anymore.
Therefore, I am wondering if there is an alternative way to create the value-version of the file that makes it possible to go back to the original file afterwards.
Something like this:
Step 1) Change all formulas to values.
Step 2) Save the version with the values in the folder.
Step 3) Undo the value-replacements in original sheet without closing it.
Do you have any idea how to solve it?
There might be a more simple way to get there, but here's how you'd create a new workbook, transfer the values over and save.
Public Sub SaveValues()
Dim newWb As Workbook
Set newWb = Workbooks.Add 'create a new workbook for the values
Dim ws As Worksheet, newWs As Worksheet
For Each ws In ThisWorkbook.Worksheets
With newWb 'create worksheets and name them in new workbook
If ws.Index = 1 Then
Set newWs = .Worksheets(1)
Else
Set newWs = .Worksheets.Add(After:=.Worksheets(.Worksheets.Count))
End If
newWs.Name = ws.Name
End With
With ws.UsedRange 'move values to new worksheet
newWs.Range("A1").Resize(.Rows.Count, .Columns.Count).Value = .Value
End With
Next
'save new workbook. If the current workbook is a .xlsb, change the .xlsm in the code below
newWb.SaveAs Replace(ThisWorkbook.FullName, ".xlsm", "_hardcoded.xlsm"), xlOpenXMLWorkbookMacroEnabled
newWb.Close
End Sub
Updated for alternatives below:
Alternative
An alternative is to use ThisWorkbook.Worksheets.Copy to copying all worksheets in one go. Unfortunately, to use this code, we have to use ActiveWorkbook to make a reference to the new workbook. (I hoped it might return a Workbook or Worksheets object)
Public Sub SaveValues2()
Dim newWB As Workbook
ThisWorkbook.Worksheets.Copy
Set newWB = ActiveWorkbook 'not great practice
Dim ws As Worksheet
For Each ws In newWB.Worksheets
With ws.UsedRange 'hardcode values
.Value = .Value
End With
Next
newWB.SaveAs Replace(ThisWorkbook.FullName, ".xlsm", "_hardcoded.xlsm"), xlOpenXMLWorkbookMacroEnabled
newWB.Close
End Sub
This is bothering me for a years now, I would like to open another workbook using VBA and copy worksheet to the current workbook and close it. Another workbook can be also macro enabled workbook. My method is following:
Application.DisplayAlerts = False
Dim workBookName1 As String
Application.AutomationSecurity = msoAutomationSecurityForceDisable
Application.AutomationSecurity = msoAutomationSecurityLow
Workbooks.Open fileName:="C:\test.xlsm", ReadOnly:=True
workBookName1 = ActiveWorkbook.Name
'some work with copying, filtering, etc.
With Workbooks(workBookName1)
.Close
End With
BUT the issue is that is not bulletproof -> sometimes this procedure closes all opened workbooks.
is there any other way to deal with this, maybe another method to try it?
If you declare and use objects properly, you will not face this problem as you will be working with only those objects. Here is an example
Option Explicit
Dim wbThis As Workbook, wbThat As Workbook
Set wbThis = ThisWorkbook
Set wbThat = Workbooks.Open(Filename:="C:\test.xlsm", ReadOnly:=True)
'
' Do some copying. For example see how I am using the objects below
' wbThat.Sheets("Sheet1").Copy After:=wbThis.Sheets(wbThis.Sheets.Count)
'
'~~> Close specific workbook when you are done
wbThat.Close (False)
Hi I'm trying to write a macro to select certain worksheets into a new file.
the tricky part is that I want to save all worksheets but 3.
I've managed to select the worksheets but I can't find how to create a new workbook and then save it.
here's my code, the sub stops at Sheets(Array(Selection)).Copy
which is not the correct command.
thanks for you help
Sub ExportPrices()
Dim ExportName As String
Dim ReportingDir As String
Dim Dashboard As String
Dim ws As Worksheet
Dashboard = ThisWorkbook.Name
ExportName = Workbooks(Dashboard).Worksheets("Macro").Range("ExportName").Value
ReportingDir = Workbooks(Dashboard).Worksheets("Macro").Range("ReportingDir").Value
Workbooks(Dashboard).Worksheets("Europe").Select
For Each ws In Worksheets
If ws.Name <> "Macro" And ws.Name <> "Dashboard" And ws.Name <> "Data" Then
ws.Select (False)
End If
Next
'create an array from selection
Sheets(Array(Selection)).Copy
ActiveWorkbook.SaveAs Filename:=ReportingDir & ExportName, _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End Sub
You must add new workbook and copy target sheet to wb:
Dim oOutBook As Workbook
Set oOutBook = Workbooks.Add
Sheets(Array(Selection)).Copy Before:=oOutBook.Sheets(1)
oOutBook.SaveAs strPathOutput
You can use the .Move method in VBA. When not presented with a location to move to, the .Move method will move the specified sheet into a new workbook.
Sheets("Yoursheet").Move
As this will always be the latest created workbook, you can then refer to this by using Workbooks.Count:
Dim wb As Workbook
Set wb = Workbooks(Workbooks.Count)
I want to be able to select a workbook and then copy the content from that workbook (sheet 1) into my current active workbook where I run the macro. I've been looking at some answers here on StackOverflow to similar questions and got the following code (see below).
The selection of a file is currently working fine, but when I run the macro it throws an error
Runtime error "438": Object does not support that method or property`
(please note, that the error comes in my native language and is just translated by me)
Sadly no object is marked that he relates to, so I can't really make out what problem he has. Yet, I guess it is a problem with the PasteSpecial in the last line of function GetTemplateData, but that code should be alright (what is it supposed to do? Save the data into the first sheet of the give workbook activeWorkbook) and pass the reference back go GeneratedValues-routine.
Option Explicit
Private Sub GenerateValues()
'Application.ScreenUpdating = False
'Application.DisplayAlerts = False
Dim activeWorkbook As Workbook
Dim activeWorksheet As Worksheet
Set activeWorkbook = Application.activeWorkbook
Set activeWorksheet = GetTemplateData(activeWorkbook)
activeWorkbook.Save
End Sub
'Get The Template Data
Private Function GetTemplateData(activeWorkbook As Workbook) As Worksheet
Dim templateWorkbook As Workbook
'Grab the Template Worksheet
Set templateWorkbook = UseFileDialogOpen
'Select all Content
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Copy
'activeWorkbook.Sheets(activeWorkbook.Sheets.Count).Range("A1", Cells.End(xlDown) & Cells.End(xlRight)).PasteSpecial xlPasteValues
activeWorkbook.Sheets(1).Range("A1", Cells.End(xlDown) & Cells.End(xlRight)).PasteSpecial xlPasteValues
End Function
'From https://learn.microsoft.com/de-de/office/vba/api/excel.application.filedialog
'Select the Workbook containing the Exported Template-Stories by User Selection
Function UseFileDialogOpen() As Workbook
Dim lngCount As Long
Dim filePath As String
Dim templateBook As Workbook
' Open the file dialog
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
.Show
Set templateBook = Workbooks.Open(.SelectedItems(1))
' Display paths of each file selected
'For lngCount = 1 To .SelectedItems.Count
' MsgBox .SelectedItems(lngCount)
'Next lngCount
End With
templateBook
End Function
I believe all of your problems originate here:
Private Sub GenerateValues()
'Application.ScreenUpdating = False
'Application.DisplayAlerts = False
Dim activeWorkbook As Workbook
Dim activeWorksheet As Worksheet
Set activeWorkbook = Application.activeWorkbook
Set activeWorksheet = GetTemplateData(activeWorkbook)
activeWorkbook.Save
End Sub
ActiveWorkbook is a defined "variable" in VBA, so it is confused as to why you are trying to reassign it. Try using a different variable name instead.
Note: although ActiveWorksheet is not a defined variable in VBA, it is close in name to ActiveSheet, so I would also change that variable name to something different just so to not confuse you when writing future code.
You could try something similar to this:
Sub CopyContentsFromOtherWorkbook()
Dim wb As Workbook
Dim twb As Workbook
filePath = "C:\File.xlsx"
Set wb = Workbooks.Open(filePath)
wb.Sheets(1).Range("A1:Z10000").Copy
Set twb = ThisWorkbook
twb.Sheets(1).Range("C1").PasteSpecial xlPasteValues
wb.Close
twb.Save
End Sub
I have written VBA code that opens up a destination workbook, copies one of the worksheets, and pastes it into the current workbook.
When I run it a second or third time etc... instead of overwriting the current worksheet, it creates a completely new one.
Ex: Worksheet is called "data", first time it transfers "data", second time "data(2)".
I have another worksheet that uses VLOOKUP function to look at some cells of this data worksheet, so it is crucial that it has correct name "data".
I thought about deleting the current (data) file before running the macro, but what if something crashes and I lose my worksheet? Is there a better solution?
NOTE: I am running the macro from the main workbook to get the sheet to be copied from the external workbook.
Sub UpdateT()
Dim wb As Workbook
Dim aw As Workbook
'Open 2nd Workbook
Set aw = Application.ActiveWorkbook
Set wb = Workbooks.Open(Filename:="C:\Users\yilmadu00\Desktop\T.xlsx")
'Copy To Different Workbook
wb.Sheets("data").Copy After:=aw.Sheets("Data1")
'Close 2nd Workbook
aw.Save
wb.Close
aw.Sheets("data").Visible = False
ActiveWorkbook.Protect ("Password")
End Sub
Function to check whether worksheet exists (credits to #ScottCrainer):
Function SheetExists(ws As String)
SheetExists = Not IsError(Application.Evaluate(ws & "!A1"))
End Function
NOTE:
It does have the issue: if A1 on the sheet contains an error it will return a false negative.
ActiveWorkbook vs ThisWorkbook, Sheets vs Worksheets
You have used 'Activeworkbook' and 'Sheet(s)' in the code so I played along.
But
Although you can have a third workbook to run the code from, I'm guessing you are running the code from a module in the 'ActiveWorkbook'. If this is true, it would be more correct to use 'ThisWorkbook' instead which always refers to the workbook that contains the code (module), to avoid accidentally running the code on a third workbook.
Sheet(s) refers to Worksheet(s) and Chartsheet(s), again I'm guessing there are no chartsheets involved in this code, therefore it would be more correct to use 'Worksheet(s)' instead of 'Sheet(s)'.
Sub UpdateT()
Const cStrPath As String = "C:\Users\yilmadu00\Desktop\T.xlsx"
Const cStrAfter As String = "Data1"
Const cStrName As String = "data"
Const cStrOld As String = "data_old"
Dim aw As Workbook '1st workbook, 'ActiveWorkbook'
Dim wb As Workbook '2nd workbook
Dim oWs As Sheet 'Each sheet in workbook 'aw'
Dim blnFound As Boolean 'True if sheet(cStrName) was found
Set aw = ActiveWorkbook 'Create a reference to the ActiveWorkbook
Set wb = Workbooks.Open(Filename:=cStrPath) 'Open 2nd Workbook
With aw
' .UnProtect ("Password")
'Check each sheet in workbook 'aw'.
For Each oWs In aw.Sheets
With oWs
'Check if there already is a sheet with the name 'cStrName'.
If .Name = cStrName Then
.Name = cStrOld 'Rename the sheet.
blnFound = True 'Sheet(cStrName) was found.
Exit For 'Immediately stop checking, there can only be one.
End If
End With
Next
End With
With wb
'Copy sheet from 2nd workbook ('wb') to workbook 'wa'.
.Sheets(cStrName).Copy After:=aw.Sheets(cStrAfter)
.Close 'Close 2nd workbook ('wb').
End With
With aw
With Application
If blnFound = True Then 'Sheet(cStrName) was found.
.DisplayAlerts = False 'Disable showing delete message.
aw.Sheets(cStrOld).Delete 'Delete old version of sheet.
.DisplayAlerts = True
End If
End With
.Sheets(cStrName).Visible = False 'Hide sheet named 'cStrName'
.Protect ("Password")
.Save 'Save workbook 'aw'.
End With
End Sub
The next time you want to do something with the sheet you have to unprotect it or the code will fail. Hidden sheets can be deleted with no problems.