I have a code which is doing following:
Prompt to choose external workbook
Copying all the data from that wb
Pasting exactly 1:1 in main wb
Close and Save from .xlsm to .xlsx but with a name of my main wb
Sub CopySheetFromClosedWorkbook2()
'Prompt to choose your file in the chosen locatioon
Dim dialogBox As FileDialog
Dim FilePath As String
Set dialogBox = Application.FileDialog(msoFileDialogOpen)
Application.StatusBar = "Choose older PDS Form!"
dialogBox.AllowMultiSelect = False
dialogBox.Title = "Select a file"
If dialogBox.Show = -1 Then
FilePath = dialogBox.SelectedItems(1)
'If nothing selected then MsgBox
Else
MsgBox "No PDS Form selected!"
Exit Sub
End If
'Here are sheets defined which you are going to copy/paste (reference update) but to keep formatting.
''Sheets should be defined from right to left to have your sheets sorted from the beginning
Dim shNames As Variant: shNames = Array("CH_or_Recipe_8", "CH_or_Recipe_7", "CH_or_Recipe_6", "CH_or_Recipe_5", "CH_or_Recipe_4", _
"CH_or_Recipe_3", "CH_or_Recipe_2", "CH_or_Recipe_1", "Customer Details", "Instructions")
Dim tgt As Workbook: Set tgt = ThisWorkbook
Application.ScreenUpdating = False
Dim src As Workbook: Set src = Workbooks.Open(FilePath)
Dim ws As Worksheet, rng As Range, i As Long
For Each ws In src.Sheets
If ws.Name Like "*[1-8]" Then
ws.Name = "CH_or_Recipe_" & Right(ws.Name, 1)
ElseIf ws.Name = "Customer_Details" Then
ws.Name = "Customer Details"
ElseIf ws.Name = "OIPT Plasmalab" Then
ws.Name = "CH_or_Recipe_1"
ElseIf ws.Name = "AMAT" Then
ws.Name = "CH_or_Recipe_2"
End If
Next
For i = 0 To UBound(shNames)
On Error Resume Next
Set ws = src.Sheets(shNames(i))
If Err.Number = 0 Then
tgt.Worksheets(shNames(i)).Cells.Clear
Set rng = ws.UsedRange
rng.Copy tgt.Worksheets(shNames(i)).Range(rng.Address)
End If
Next i
src.Close False
Application.ScreenUpdating = True
MsgBox "Copy&Paste successful!"
End Sub
Sub SaveNoMacro()
Dim fn As String
With ThisWorkbook
fn = Replace(.FullName, ".xlsm", ".xlsx")
Application.DisplayAlerts = False
.SaveAs fn, FileFormat:=xlWorkbookDefault
Application.DisplayAlerts = True
End With
MsgBox "Saved as " & fn
End Sub
What I just need (if possible) is to save my wb in the same name as that external wb that I am taking data from and adding date/time at the end.
Example:
MainWB1.xlsm + ExternalWB1.xlsx >>> MainWB1.xlsx (This is now)
MainWB1.xlsm + ExternalWB1.xlsx >>> ExternalWB1_today().xlsx (This is what I wanna)
You have 2 separate methods:
CopySheetFromClosedWorkbook2
SaveNoMacro
The name of the source workbook is only available in the scope of the CopySheetFromClosedWorkbook2 because that's where you open and close it. So, you have 2 options:
Save the main workbook before exiting the scope of the CopySheetFromClosedWorkbook2 method i.e. while the name of the source book is available
Save the name of the source book somewhere (global variable, named range, registy, custom xml part etc.) or even return it as a result (Function instead of Sub) so that you can call the SaveNoMacro method at a later stage
Save before exiting the scope
Here are 2 ways to do this:
Place your save code before the src.Close False line so that you can use the src.Name property i.e. combine the 2 methods into one. Not sure if you want to do this
Pass the name as an argument to the second method. In CopySheetFromClosedWorkbook2 replace this:
src.Close False
with this:
SaveNoMacro src.Name
src.Close False
and update SaveNoMacro to:
Sub SaveNoMacro(ByVal newName As String)
Dim fn As String
With ThisWorkbook
fn = Replace(.FullName, .Name, Left(newName, InStrRev(newName, ".") - 1)) _
& Format$(Date, "_yyyy-mm-dd") & ".xlsx"
Application.DisplayAlerts = False
.SaveAs fn, FileFormat:=xlWorkbookDefault
Application.DisplayAlerts = True
End With
MsgBox "Saved as " & fn
End Sub
Save the name for later use
In case you don't want to run the 2 methods in a sequence then you can save the name for later use. Using a global variable is not a good idea as the state can be lost by the time you run the save method. Using a named range would work as long as you don't have your workbook protected i.e you can create a named range.
There are many options but the easiest to use is to write to registry using the built in SaveSetting option. Replace this:
src.Close False
with this:
SaveSetting "MyApp", "MySection", "NewBookName", src.Name
src.Close False
and update SaveNoMacro to:
Sub SaveNoMacro()
Dim fn As String: fn = GetSetting("MyApp", "MySection", "NewBookName")
If LenB(fn) = 0 Then
MsgBox "No name was saved", vbInformation, "Cancelled"
Exit Sub
Else
DeleteSetting "MyApp", "MySection", "NewBookName"
End If
With ThisWorkbook
fn = Replace(.FullName, .Name, Left(fn, InStrRev(fn, ".") - 1)) _
& Format$(Date, "_yyyy-mm-dd") & ".xlsx"
Application.DisplayAlerts = False
.SaveAs fn, FileFormat:=xlWorkbookDefault
Application.DisplayAlerts = True
End With
MsgBox "Saved as " & fn
End Sub
fn = Replace(.FullName, ".xlsm", ".xlsx")
fn = Replace(.FullName, ".xlsm", date & ".xlsx")
What I just need (if possible) is to save my wb in the same name as that external wb that I am taking data from and adding date/time at the end
You got the full path of your external wb in the variable FilePath so you can use that to save the workbook. You could save it like this (at the end of your sub CopySheetFromClosedWorkbook2):
Dim SaveName As String
SaveName = src.Path & "\" & Replace(Split(Filepath, "\")(UBound(Split(Filepath, "\"))), ".xlsm", Format(Date, "dd_mm_yyyy") & ".xlsx")
With ThisWorkbook
Application.DisplayAlerts = False
.SaveAs SaveName, FileFormat:=xlWorkbookDefault
Application.DisplayAlerts = True
End With
Notice I'm using the object src to get the path where you want to save the new workbook, so you need to asign the line SaveName = .... anywhere before you do src.Close.
Related
i got a variable:
V_WBNameOutPut as string
and use it inside the following code:
Application.Workbooks(V_WBNameOutPut).Activate
This two part of code are inside a huger code which work fine for 99.99% of different users, but only for one user the code go in error and when I debug its stop to Application.Workbooks(V_WBNameOutPut).Activate line.
And the error is the following:
Runtime Error 9: Subscript Out of Range
Any ideas why this happend and possible solution?
Thanks
I try it to debug but the code works fine but for one particular user it doesn't
The subroutine to generate the output file, which the Application.Workbooks(V_WBNameOutPut).Activate refers to:
Sub CreateWB()
Dim File_Name As Variant
Dim File_Name_Saved As String
Dim i_attempt As Integer
Dim NewWorkBook As Workbook
Set NewWorkBook = Workbooks.Add
Do While i_attempt < 2
i_attempt = i_attempt + 1
File_Name = Application.GetSaveAsFilename(InitialFileName:=V_WBNameOutPut, filefilter:="Excel Files(*.xlsx),*.xlsx,Excel-Macro Files (*.xlsm),*.xlsm", Title:="Please choose a Folder")
File_Name_Saved = Left(Right(File_Name, Len(V_WBNameOutPut) + 5), Len(V_WBNameOutPut))
If File_Name = False Then
ActiveWorkbook.Close
End
Else
If UCase(File_Name_Saved) <> UCase(V_WBNameOutPut) Then
If i_attempt < 2 Then
MsgBox "Please do not change the File name" & vbCrLf & i_attempt & "/2 Attempt"
Else
ActiveWorkbook.Close
End
End If
Else
Application.DisplayAlerts = False
NewWorkBook.SaveAs File_Name, ConflictResolution:=True
Exit Do
End If
End If
Loop
End Sub
You can loop through the open workbooks looking for a match without the file extension. A better solution would be to make CreateWB a function that returns the saved filename.
Option Explicit
Dim V_WBNameOutPut
Sub test()
Dim wb As Workbook
V_WBNameOutPut = "test2"
CreateWB
For Each wb In Workbooks
If wb.Name Like V_WBNameOutPut & "*" Then
wb.Activate
Exit For
End If
Next
Sheets(1).Cells(1, 1).Select ' active workbook
End Sub
Sub CreateWB()
Dim NewWorkBook As Workbook
Dim fso As Object, bSaveOK As Boolean, i_attempt As Integer
Dim File_Name As Variant, File_Name_Saved As String
Set fso = CreateObject("Scripting.FileSystemObject")
For i_attempt = 1 To 2
File_Name = Application.GetSaveAsFilename( _
InitialFileName:=V_WBNameOutPut, _
filefilter:="Excel Files(*.xlsx),*.xlsx,Excel-Macro Files (*.xlsm),*.xlsm", _
Title:="Please choose a Folder")
If File_Name = False Then Exit Sub
bSaveOK = (fso.getbasename(File_Name) = V_WBNameOutPut)
If Not bSaveOK And i_attempt = 1 Then
MsgBox "Please do not change the File name from " & V_WBNameOutPut _
& vbCrLf & i_attempt & "/2 Attempt"
Else
Exit For
End If
Next
' create workbook and save
If bSaveOK Then
Set NewWorkBook = Workbooks.Add
Application.DisplayAlerts = False
NewWorkBook.SaveAs File_Name, ConflictResolution:=True
Application.DisplayAlerts = True
End If
End Sub
I have a template file and 4 source documents that I use to fill the template. For each row in sheet2, I create a new blank template and fill it out, resulting in somewhere between 10-100 files. I want to save these in a loop, but having issues with Excel force closing on me. This is my code so far, recycled from a different project.
Dim w As Long, wb As Workbook
Dim fp As String, fn As String
Dim folderName As String
Dim fsoFSO
On Error GoTo bm_Safe_Exit
'Application.ScreenUpdating = False 'stop screen flashing
Application.DisplayAlerts = False 'stop confirmation alerts
'start with a reference to ThisWorkbook
With ThisWorkbook
folderName = Format(Date, "ddmmyyyy")
'set path to save
'fp = "<PATH HERE>" & folderName
fp = "C:\Users\Username\OneDrive - CompanyName\Documents\Projects\ThisProject\csvOutput\" & folderName
Set fsoFSO = CreateObject("Scripting.FileSystemObject")
If fsoFSO.FolderExists(fp) Then
MsgBox "FOLDER - " & fp & " ALREADY EXISTS, DELETE CONTENTS TO PROCEED"
Exit Sub
Else
fsoFSO.CreateFolder (fp)
End If
'cycle through each of the worksheets
For w = 6 To Worksheets.Count
With Worksheets(w)
.Copy
'the ActiveWorkbook is now the new workbook populated with a copy of the current worksheet
With ActiveWorkbook
fn = .Worksheets(1).Name
Cells.Select
Selection.SpecialCells(xlCellTypeVisible).Copy
Worksheets.Add after:=Sheets(Sheets.Count)
Range("A1").Select
ActiveSheet.Paste
Worksheets(1).Delete
Worksheets(1).Name = fn
.SaveAs Filename:=fp & Chr(92) & fn, FileFormat:=51
.Close savechanges:=False '<~~ already saved in line above
End With
End With
Next w
End With
bm_Safe_Exit:
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub ```
The code below worked for me: not sure exactly where the problem might vbe with your posted code, but within your With blocks not everything is scope to the block using a leading .
Sub Test()
Dim w As Long, wb As Workbook, wbNew As Workbook
Dim fp As String, fn As String
Dim fsoFSO
On Error GoTo bm_Safe_Exit
Set wb = ThisWorkbook
fp = "C:\Users\Username\OneDrive - CompanyName\Documents\Projects\" & _
"ThisProject\csvOutput\" & Format(Date, "ddmmyyyy") & "\"
Set fsoFSO = CreateObject("Scripting.FileSystemObject")
If fsoFSO.FolderExists(fp) Then
MsgBox "FOLDER - " & fp & " ALREADY EXISTS, DELETE CONTENTS TO PROCEED"
Exit Sub
Else
fsoFSO.CreateFolder fp
End If
'cycle through each of the worksheets
For w = 6 To wb.Worksheets.Count
'explicitly create a new single-sheet workbook as the destination
Set wbNew = Workbooks.Add(Template:=xlWBATWorksheet)
wb.Worksheets(w).Copy before:=wbNew.Sheets(1)
DeleteSheet wbNew.Sheets(2)
With wbNew
fn = .Worksheets(1).Name
.Worksheets.Add after:=.Worksheets(.Worksheets.Count)
.Worksheets(1).Cells.SpecialCells(xlCellTypeVisible).Copy _
Destination:=.Worksheets(2).Range("A1")
DeleteSheet .Worksheets(1)
.Worksheets(1).Name = fn
.SaveAs Filename:=fp & fn, FileFormat:=51
.Close savechanges:=False '<~~ already saved in line above
End With
Next w
Exit Sub
bm_Safe_Exit:
MsgBox Err.Description
End Sub
'utility sub
Sub DeleteSheet(ws As Worksheet)
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End Sub
I have workbook that has multiple sheets and need a macro button to save a copy of it and delete the sheet named "CSG". This was easy to do, but the problem was that all cell references pointed to the original workbook.
With help, the problem has been tried to solve through name manager and break all links-code. Now the problem is that it break all references within the new workbook and copies only the values from the original workbook.
For example, in the original workbook sheet1 cell A1 has value 10, sheet2 cell A1 has cell reference "='sheet1'!A1". When I make the new copy, both cells do have the value 10, but the reference is no longer there.
Is there a way to keep these references within the workbook without them referencing the original workbook? Below is the code currently being used.
Sub SaveTest()
Dim x As Integer
Dim FileName As String, FilePath As String
Dim NewWorkBook As Workbook, OldWorkBook As Workbook
Set OldWorkBook = ThisWorkbook
With Application
.ScreenUpdating = False: .DisplayAlerts = False
End With
On Error Resume Next
With OldWorkBook.Sheets("CSG")
FilePath = "C:\Users\Tom\Desktop\" & .Range("B1").Value & " " & .Range("B2").Value
FileName = .Range("B1").Value & " " & .Range("B2").Value & ".xlsx"
End With
MkDir FilePath
On Error GoTo -1
On Error GoTo myerror
FilePath = FilePath & "\"
For x = 2 To OldWorkBook.Worksheets.Count
With OldWorkBook.Worksheets(x)
If Not NewWorkBook Is Nothing Then
.Copy after:=NewWorkBook.Worksheets(NewWorkBook.Worksheets.Count)
Else
.Copy
Set NewWorkBook = ActiveWorkbook
End If
End With
Next x
DeleteBadNames NewWorkBook
BreakAllLinks NewWorkBook
UpdateNameManager NewWorkBook
NewWorkBook.SaveAs FilePath & FileName, 51
myerror:
If Not NewWorkBook Is Nothing Then NewWorkBook.Close False
With Application
.ScreenUpdating = True: .DisplayAlerts = True
End With
If Err <> 0 Then MsgBox (Error(Err)), 48, "Error"
End Sub
Create a Copy of a Workbook
Option Explicit
Sub SaveTest()
Dim OldWorkBook As Workbook: Set OldWorkBook = ThisWorkbook
Dim WorkSheetNames() As String
Dim FilePath As String
Dim FileName As String
With OldWorkBook.Worksheets("CSG")
ReDim WorkSheetNames(1 To .Parent.Worksheets.Count)
FilePath = "C:\Users\Tom\Desktop\" & .Range("B1").Value & " " _
& .Range("B2").Value
FileName = .Range("B1").Value & " " & .Range("B2").Value & ".xlsx"
End With
On Error Resume Next
MkDir FilePath
On Error GoTo 0
FilePath = FilePath & "\"
Dim ws As Worksheet
Dim n As Long
For Each ws In OldWorkBook.Worksheets
n = n + 1
WorkSheetNames(n) = ws.Name
Next ws
Application.ScreenUpdating = False
OldWorkBook.Worksheets(WorkSheetNames).Copy
With ActiveWorkbook ' new workbook
Application.DisplayAlerts = False
.Worksheets("CSG").Delete
.SaveAs FilePath & FileName, 51 ' xlOpenXMLWorkbook
Application.DisplayAlerts = True
'.Close SaveChanges:=False
End With
Application.ScreenUpdating = True
End Sub
Hello and thank you for your time, in the function code below, how do I make it in a way that it will function on any users computer, not just mine.
I know I need to probably use the Environ("USERPROFILE") thing but I don't know how to incorporate it in the code below.
Function Import_Data() As Boolean
Dim x As Workbook
Dim targetWorkbook As Workbook
Dim xWs As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Const F_PATH As String = "C:\Users\mohammad.reza\Desktop\MyFiles.xls"
'if no file then exit and return false
If Dir(F_PATH) = "" Then
MsgBox "My Files is not found on your Desktop"
Import_Data = False
Exit Function
End If
'If the file exists than load the file and continue
Import_Data = True
' This part delets all sheets except the summary tab
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name <> "Summary" Then
xWs.Delete
End If
Next
' This part will get the raw data from the downloaded file on the desktop
Set x = Workbooks.Open("C:\Users\mohammad.reza\Desktop\MyFiles.xls")
Set targetWorkbook = Application.ActiveWorkbook
' This part will copy the sheet into this workbook
With x.Sheets("MyFiles").UsedRange
ThisWorkbook.Sheets.Add(After:=Sheets(Sheets.Count)).Range("A1").Resize( _
.Rows.Count, .Columns.Count) = .Value
End With
x.Close
' This part will rename the sheet and move it to the end
ActiveSheet.Name = "RAW DATA"
ActiveSheet.Move After:=Worksheets(Worksheets.Count)
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Function
Thank you brad for your answer, however when I use it, it gives the below error:
Try this ...
Function Import_Data() As Boolean
Dim x As Workbook
Dim targetWorkbook As Workbook
Dim xWs As Worksheet
Dim sPath As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
sPath = Environ("USERPROFILE") & "\Desktop\MyFiles.xls"
'if no file then exit and return false
If Dir(sPath) = "" Then
MsgBox "My Files is not found on your Desktop"
Import_Data = False
Exit Function
End If
'If the file exists than load the file and continue
Import_Data = True
' This part delets all sheets except the summary tab
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name <> "Summary" Then
xWs.Delete
End If
Next
' This part will get the raw data from the downloaded file on the desktop
Set x = Workbooks.Open(sPath)
Set targetWorkbook = Application.ActiveWorkbook
' This part will copy the sheet into this workbook
With x.Sheets("MyFiles").UsedRange
ThisWorkbook.Sheets.Add(After:=Sheets(Sheets.Count)).Range("A1").Resize( _
.Rows.Count, .Columns.Count) = .Value
End With
x.Close
' This part will rename the sheet and move it to the end
ActiveSheet.Name = "RAW DATA"
ActiveSheet.Move After:=Worksheets(Worksheets.Count)
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Function
I am trying to copy specific collections sheets within an excel workbook in separate workbooks. Not being a vba coder I have used and adapted code found here and other resource sites. I believe I am now very close having grasped the basic concepts but cannot figure out what i am doing wrong, triggering the below code causes the first new workbook to be created and the first sheet inserted but breaks at that point.
My code is below, additional relevant info - there is a sheet called 'List' which has a column of names. Each name on the list has 2 sheets which I am trying to copy 2 by 2 into new sheet of the same name. the sheets are labelled as the name and the name + H (e.g Bobdata & BobdataH)
Sub SheetCreate()
'
'Creates an individual workbook for each worksname in the list of names.
'
Dim wbDest As Workbook
Dim wbSource As Workbook
Dim sht As Object
Dim strSavePath As String
Dim sname As String
Dim relativePath As String
Dim ListOfNames As Range, LRow As Long, Cell As Range
With ThisWorkbook
Set ListSh = .Sheets("List")
End With
LRow = ListSh.Cells(Rows.Count, "A").End(xlUp).Row '--Get last row of list.
Set ListOfNames = ListSh.Range("A1:A" & LRow) '--Qualify list.
With Application
.ScreenUpdating = False '--Turn off flicker.
.Calculation = xlCalculationManual '--Turn off calculations.
End With
Set wbSource = ActiveWorkbook
For Each Cell In ListOfNames
sname = Cell.Value & ".xls"
relativePath = wbSource.Path & "\" & sname
Sheets(Cell.Value).Copy
Set wbDest = ActiveWorkbook
Application.DisplayAlerts = False
ActiveWorkbook.CheckCompatibility = False
ActiveWorkbook.SaveAs Filename:=relativePath, FileFormat:=xlExcel8
Application.DisplayAlerts = True
wbSource.Activate
Sheets(Cell.Value & "H").Copy after:=Workbooks(relativePath).Sheets(Cell.Value)
wbDest.Save
wbDest.Close False
Next Cell
MsgBox "Done!"
End Sub
You can try to change
Sheets(Cell.Value & "H").Copy after:=Workbooks(relativePath).Sheets(Cell.Value)
to
Sheets(Cell.Value & "H").Copy after:=wbDest.Sheets(Cell.Value)
Also it would be good idea to check if file already exists in selected location. For this you can use function:
Private Function findFile(ByVal sFindPath As String, Optional sFileType = ".xlsx") As Boolean
Dim obj_fso As Object: Set obj_fso = CreateObject("Scripting.FileSystemObject")
findFile = False
findFile = obj_fso.FileExists(sFindPath & "/" & sFileType)
Set obj_fso = Nothing
End Function
and change sFileType = ".xlsx" to "*" or other excet file type.
This was the code i created to create a new workbook and then copy sheet contents from existing one to the new one. Hope it helps.
Private Sub CommandButton3_Click()
On Error Resume Next
Application.ScreenUpdating = False
Application.DisplayAlerts = False
TryAgain:
Flname = InputBox("Enter File Name :", "Creating New File...")
MsgBox Len(Flname)
If Flname <> "" Then
Set NewWkbk = Workbooks.Add
ThisWorkbook.Sheets(1).Range("A1:J100").Copy
NewWkbk.Sheets(1).Range("A1:J100").PasteSpecial
Range("A1:J100").Select
Selection.Columns.AutoFit
AddData
Dim FirstRow As Long
Sheets("Sheet1").Range("A1").Value = "Data Recorded At-" & Format(Now(), "dd-mmmm-yy-h:mm:ss")
NewWkbk.SaveAs ThisWorkbook.Path & "\" & Flname
If Err.Number = 1004 Then
NewWkbk.Close
MsgBox "File Name Not Valid" & vbCrLf & vbCrLf & "Try Again."
GoTo TryAgain
End If
MsgBox "Export Complete Close the Application."
NewWkbk.Close
End If
End Sub