I want to copy a range between sheets using for..next, I have working loop, I don't know how to define a range that will change for each x in my loop, the range should be cells to the right of x in columns B and C.
Sub macro_cpt()
Dim Wiazka As String
Application.ScreenUpdating = False
Set w = Sheets("data_test")
w.Select
ActiveSheet.AutoFilterMode = False
owx = Cells(Rows.Count, "A").End(xlUp).Row
For x = 2 To owx Step 3
Wiazka = Cells(x, "A")
If Not SheetExists(ActiveWorkbook, Wiazka) Then
Sheets.Add(After:=Sheets(Sheets.Count)).Name = Wiazka
Else
Sheets(Wiazka).Cells.ClearContents
End If
w.Select
????? Range ?????.Copy Sheets(Wiazka).Range("A1")
Next
Set W = Nothing
i = MsgBox("done.", vbInformation)
ActiveSheet.AutoFilterMode = False
Application.ScreenUpdating = True
ActiveWorkbook.Close SaveChanges:=False
End Sub
Function SheetExists(Wb As Workbook, ShName As String) As Boolean
For Each s In Wb.Sheets
If s.Name = ShName Then
SheetExists = True
Exit Function
End If
Next
End Function
Copy to All Worksheets Except the First
In a worksheet (source) of the workbook containing this code (ThisWorkbook), in column A starting from the second row (A2), it will loop through each 3rd cell (containing a destination worksheet name) and copy the values from columns B:C in the current row, to cell A1 of each destination worksheet.
Option Explicit
Sub macro_cpt()
' Source
Const sName As String = "data_test"
Const sFirstRow As Long = 2
Const sCol As String = "A" ' column of the destination worksheet names
Const sStep As Long = 3 ' rows 2, 5, 8...
Const sCols As String = "B:C" ' columns of data to be copied
' Destination
Const dAddress As String = "A1"
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Or:
'Dim wb As Workbook: Set wb = ActiveWorkbook ' workbook you're looking at
' Source
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim sLastRow As Long
sLastRow = sws.Cells(sws.Rows.Count, sCol).End(xlUp).Row
Dim scrg As Range: Set scrg = sws.Columns(sCols) ' Source Column Range
' The source and destination row ranges have the same number of columns.
Dim cCount As Long: cCount = scrg.Columns.Count
Application.ScreenUpdating = False
ActiveSheet.AutoFilterMode = False
Dim srrg As Range ' Source Row Range
Dim dws As Worksheet
Dim drrg As Range ' Destination Row Range
Dim dName As String
Dim r As Long
For r = sFirstRow To sLastRow Step sStep
dName = sws.Cells(r, sCol)
' You don't want to (accidentally) write to the source worksheet.
If StrComp(dName, sName, vbTextCompare) <> 0 Then
If IsSheetNameTaken(wb, dName) Then ' all sheets, charts included
Set dws = wb.Worksheets(dName) ' error if chart
dws.Cells.ClearContents
Else ' worksheet doesn't exist
Set dws = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
dws.Name = dName
End If
Set srrg = scrg.Rows(r)
Set drrg = dws.Range(dAddress).Resize(, cCount)
' Copy values only (most efficiently)
drrg.Value = srrg.Value
' Copy values, formulas and formats.
'srrg.Copy drrg
'Else ' it's the source worksheet
End If
Next r
sws.Activate
'wb.Save ' uncomment after testing
Application.ScreenUpdating = True
MsgBox "Data distributed among worksheeets.", _
vbInformation, "Distribute Data"
'wb.Close ' uncomment after testing
End Sub
Function IsSheetNameTaken( _
ByVal wb As Workbook, _
ByVal SheetName As String) _
As Boolean
On Error Resume Next
Dim sh As Object: Set sh = wb.Worksheets(SheetName)
On Error GoTo 0
IsSheetNameTaken = Not sh Is Nothing
End Function
Related
I'm relatively new to VBA and I'm trying to move data from one workbook to another. Specifically I'm trying to move row elements from the first workbook which can be selected using the code I have and move it to Book1 in a specific way. My current goal is to move elements from the 3rd row of the selected file and copy each cell of that row 358 times down column C and then move to the next cell in the row and copy it 358 times as well. The row contains 62 elements which each have to be copied 358 times down a column. The row starts from column 2.
The code I'm using is :
Dim SelectedBook As Workbook
Dim lastRow As String
Dim i As Long
Dim j As Long
Dim n As Long
i = 1
j = 1
n = 2
FileToOpen = Application.GetOpenFilename(Filefilter:="Excel Files (*.xls*), *.xls*", Title:="Select FIles")
Do While n <= 62
Do While j <= 358
Set OpenBook = Application.Workbooks.Open(FileToOpen)
Cells(3, n).Select
Selection.Copy
Windows("Book1").Activate
lastRow = ActiveSheet.Cells(Rows.Count, "C").End(xlUp).Row + 1
Range("C" & lastRow).Select
Selection.PasteSpecial
ActiveSheet.Paste
j = j + 1
Loop
j = 1
n = n + 1
Loop
End Sub
The copying happens but because it is happening cell by cell its taking forever due to there being so many cells and the repetition as well. Is there anyway to speed this up in such a way that it can run faster? Any help would be appreciated, thanks in advance!
Transpose Headers Repeatedly
It will open the selected file and copy the data to a newly created single-worksheet workbook. First, test it as-is and adjust the numbers. If you have a preceding code not posted here, move the lines, creating the workbook, to the beginning of the code and use dwb (and dws) instead of (activating) Windows("Book1").
Sub TransposeHeaders()
Const dReps As Long = 358
' Open the source file.
Dim sPath: sPath = Application.GetOpenFilename( _
Filefilter:="Excel Files (*.xls*), *.xls*", Title:="Select FIles")
If VarType(sPath) = vbBoolean Then
MsgBox "No file selected.", vbExclamation
Exit Sub
End If
' Write the values from the source worksheet to the source array.
Dim swb As Workbook: Set swb = Workbooks.Open(sPath)
Dim sws As Worksheet: Set sws = swb.Worksheets(1) ' adjust e.g. "Sheet1"
Dim srg As Range
Set srg = sws.Range("B3", sws.Cells(3, sws.Columns.Count).End(xlToLeft))
Dim sData(): sData = srg.Value
' Write the values from the source to the destination array.
Dim scCount As Long: scCount = srg.Columns.Count
Dim dData(): ReDim dData(1 To scCount * dReps, 1 To 1)
Dim sValue, sc As Long, dRep As Long, dr As Long
For sc = 1 To scCount
sValue = sData(1, sc)
For dRep = 1 To dReps
dr = dr + 1
dData(dr, 1) = sValue
Next dRep
Next sc
' Write the values from the destination array to the destination range.
' Add and reference a new single-worksheet workbook.
Dim dwb As Workbook: Set dwb = Workbooks.Add(xlWBATWorksheet)
' Reference its only worksheet.
Dim dws As Worksheet: Set dws = dwb.Sheets(1) ' the one and only
' Reference the destination range.
Dim dfCell As Range: Set dfCell = dws.Range("C2")
Dim drg As Range: Set drg = dfCell.Resize(dr)
' Write the values from the destination array to the destination range.
drg.Value = dData
' Close the source workbook.
swb.Close SaveChanges:=False
End Sub
Here's some commented code that should help you understand how to write what you're looking for:
Sub ImportData()
'Import data from StartCol to FinalCol, from CopyRow, a total of CopyTimes
Const sStartCol As String = "B"
Const sFinalCol As String = "BK"
Const lCopyRow As Long = 3
Const lCopyTimes As Long = 358
'Data imported will be placed in DestCol
Const sDestCol As String = "C"
'Option to clear previous data before importing
'Set this to false if you want to keep prior data
Const bClearPrevious As Boolean = True
'Declare and define destination variables
Dim wbDest As Workbook: Set wbDest = ThisWorkbook
Dim wsDest As Worksheet: Set wsDest = wbDest.Worksheets("Sheet1") 'Set this to correct worksheet in destination workbook
'Prompt for source file
Dim sSourceFile As String
sSourceFile = Application.GetOpenFilename("Excel Files (*.xls*), *.xls*", , "Select Import File", MultiSelect:=False)
If sSourceFile = "False" Then Exit Sub 'Pressed cancel
'Clear previous results if option is set to true
If bClearPrevious = True Then wsDest.Range(sDestCol & 2, wsDest.Cells(wsDest.Rows.Count, sDestCol).End(xlUp)).ClearContents
Dim lColIndex As Long
Dim sSourceSheet as String
With Workbooks.Open(sSourceFile)
'Specify correct worksheet for the source workbook names here
Select Case .Name
Case "Book1.xlsx": sSourceSheet = "Sheet1"
Case "Book2.xlsx": sSourceSheet = "Sheet10"
Case "Book3.xlsx", "Book4.xlsx": sSourceSheet = "DataSheet"
Case Else: sSourceSheet = "Sheet1" 'If the other cases aren't found, it will default to the Case Else
End Select
With .Worksheets(sSourceSheet)
For lColIndex = .Columns(sStartCol).Column To .Columns(sFinalCol).Column
wsDest.Cells(wsDest.Rows.Count, sDestCol).End(xlUp).Offset(1).Resize(lCopyTimes).Value = .Cells(lCopyRow, lColIndex).Value
Next lColIndex
End With
.Close False 'Close source file, don't save changes
End With
End Sub
There are a lot of VBA examples that produce and index list containing the name of the excel sheets (with hyperlinks).
Based on that, lets say we have:
An undefinite number of crosstables in one excel sheet.
A title exactly before each table (which are not actual tables from excel but cell ranges).
First title is always in range A4.
Always one empty row between tables.
Could we identify with VBA the cells where the titles are and create an index list with them?
Create an Index List of Tables in a Worksheet
Sub CreateTableList()
' Define constants.
Const SRC_NAME As String = "Sheet1"
Const SRC_FIRST_CELL As String = "A4"
Const SRC_EMPTY_ROWS As Long = 1 ' has to be > 0
Const DST_NAME As String = "List"
Const DST_FIRST_CELL As String = "A1"
Dim dHeaders(): dHeaders = VBA.Array("ID", "Table Name", "Table Rows")
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Source
Dim sws As Worksheet: Set sws = wb.Sheets(SRC_NAME)
Dim sCell As Range: Set sCell = sws.Range(SRC_FIRST_CELL)
Dim srg As Range: Set srg = sCell.CurrentRegion
Dim srCount As Long: srCount = srg.Rows.Count
If srCount = 1 Then
MsgBox "No data found.", vbCritical
Exit Sub
End If
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Do While srCount > 1
dict(srg.Cells(1)) = srCount - 2
Set sCell = sCell.Offset(srCount + SRC_EMPTY_ROWS)
Set srg = sCell.CurrentRegion
srCount = srg.Rows.Count
Loop
' Destination
Application.ScreenUpdating = False
Dim dws As Worksheet
' Check if the destination worksheet exists.
On Error Resume Next
Set dws = wb.Sheets(DST_NAME)
On Error GoTo 0
' Delete it if it exists.
If Not dws Is Nothing Then
Application.DisplayAlerts = False
dws.Delete
Application.DisplayAlerts = True
End If
' Add new.
Set dws = wb.Sheets.Add(Before:=wb.Sheets(1)) ' first
dws.Name = DST_NAME
Dim dfCell As Range: Set dfCell = dws.Range(DST_FIRST_CELL)
Dim dhrg As Range: Set dhrg = dfCell.Resize(, UBound(dHeaders) + 1)
Dim ddrg As Range: Set ddrg = dhrg.Offset(1).Resize(dict.Count)
' Copy and format.
With dhrg ' headers
.Value = dHeaders
.Font.Bold = True
End With
With ddrg ' data
.Columns(1).Value = dws.Evaluate("ROW(1:" & dict.Count & ")")
.Columns(2).Value = Application.Transpose(dict.Keys)
.Columns(3).Value = Application.Transpose(dict.Items)
.EntireColumn.AutoFit
End With
Application.ScreenUpdating = True
' Inform.
MsgBox "List created.", vbInformation
End Sub
I am really struggling in creating a macro that from a master Excel file creates multiple Excel files based on the values in the first column. More specifically, I have in column "A" some categories, and based on all the categories (ITT1, ITT2, ITT3, ITT4 and ITT5) I would like to create multiple excel files containing the sheet with just 1 category. At the moment, I have been able to save just 1 file with 1 category. But I cannot do it with multiple. Could you kindly help me please? I am stuck.
Sub Split()
Dim location As String
location = "Z:\Incent_2022\ORDINARIA\RETAIL-WHS\Andamento\Q4\Andamento\Novembre\And. Inc Q4_ITT1.xlsm"
ActiveWorkbook.SaveAs Filename:=location, FileFormat:=52
With ActiveSheet
Const FirstRow As Long = 6
Dim LastRow As Long
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' get last used row in column A
Dim Row As Long
For Row = LastRow To FirstRow Step -1
If Not .Range("A" & Row).Value = "ITT1" Then
.Range("A" & Row).EntireRow.Delete
End If
Next Row
End With
ActiveWorkbook.Close SaveChanges:=True
End Sub
This is working for me perfectly. There are a few things you will need to change to fit your sheet.
Option Explicit
Sub Export_Files()
Dim I As Long
Dim lRow As Long
Dim SaveLoc As String
Dim OutWB As Workbook
Dim TypeList
Dim TypeRG As Range
' > Create Unique List of Used Types
lRow = Range("A" & Rows.Count).End(xlUp).Row
Set TypeRG = Sheet1.Range("A2:A" & lRow)
TypeList = Application.WorksheetFunction.Unique(TypeRG)
' > My Directory
SaveLoc = "C:\Users\cameron\Documents\temp\"
' >
For I = 1 To UBound(TypeList, 1)
'Create File:
Set OutWB = Workbooks.Add
OutWB.SaveAs SaveLoc & TypeList(I, 1)
'Transfer Data to file:
Sheet1.Range("A1:E" & lRow).AutoFilter Field:=1, Criteria1:=TypeList(I, 1)
Sheet1.Range("A1:E" & lRow).SpecialCells(xlCellTypeVisible).Copy
OutWB.Worksheets(1).Paste
OutWB.Save
OutWB.Close
Next I
End Sub
To Change:
SaveLoc - to your preferred directory
The TypeRG range if yours is not in A Column (also your lRow maybe)
your autofilter range if your data range is larger than mine.
Exaple of my data:
Export Split Data
Sub ExportSplitData()
' Define constants.
Const SRC_NAME As String = "Sheet1"
Const SRC_FIRST_CELL As String = "A5"
Const SRC_CRITERIA_COLUMN As Long = 1
Const DST_FOLDER As String _
= "Z:\Incent_2022\ORDINARIA\RETAIL-WHS\Andamento\Q4\Andamento\Novembre\"
Const DST_NAME_LEFT As String = "And. Inc Q4_"
Const DST_EXTENSION As String = ".xlsm"
' Reference the Source worksheet.
Dim swb As Workbook: Set swb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = swb.Sheets(SRC_NAME)
Application.ScreenUpdating = False
' To leave the source workbook intact, export the worksheet
' to a new (helper) workbook and reference the range (there).
sws.Copy
Dim hwb As Workbook: Set hwb = Workbooks(Workbooks.Count)
Dim hws As Worksheet: Set hws = hwb.Sheets(SRC_NAME)
If hws.FilterMode Then hws.ShowAllData
Dim hfCell As Range: Set hfCell = hws.Range(SRC_FIRST_CELL)
Dim hrg As Range, hdrg As Range, hfrrg As Range, hrCount As Long
With hws.UsedRange
Set hfrrg = Intersect(hfCell.EntireRow, .Cells)
Set hrg = hfrrg.Resize(.Rows.Count + .Row - hfrrg.Row)
hrCount = hrg.Rows.Count
Set hdrg = hrg.Resize(hrCount - 1).Offset(1) ' no headers
End With
' Sort the range by the criteria column.
hrg.Sort hrg.Columns(SRC_CRITERIA_COLUMN), xlAscending, , , , , , xlYes
' Write the unique values from the criteria column to a dictionary.
Dim hData() As Variant: hData = hdrg.Columns(SRC_CRITERIA_COLUMN).Value
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim r As Long
For r = 1 To hrCount - 1
If Len(CStr(hData(r, 1))) > 0 Then
dict(hData(r, 1)) = Empty
End If
Next r
' Loop through the keys of the dictionary and export
' the sorted helper worksheet to be processed in yet another file,
' the destination workbook.
Dim dwb As Workbook, dws As Worksheet, drg As Range, ddrg As Range
Dim rKey As Variant, dFilePath As String
For Each rKey In dict.Keys
hws.Copy
Set dwb = Workbooks(Workbooks.Count)
Set dws = dwb.Sheets(SRC_NAME)
Set drg = dws.Range(hrg.Address) ' has headers
Set ddrg = dws.Range(hdrg.Address) ' no headers
drg.AutoFilter SRC_CRITERIA_COLUMN, "<>" & rKey ' filter
ddrg.SpecialCells(xlCellTypeVisible).Delete xlShiftUp ' delete
dws.AutoFilterMode = False ' turn off filter
dFilePath = DST_FOLDER & DST_NAME_LEFT & rKey & DST_EXTENSION
Application.DisplayAlerts = False
dwb.SaveAs dFilePath, xlOpenXMLWorkbookMacroEnabled
Application.DisplayAlerts = True
dwb.Close SaveChanges:=False
Next rKey
' Close the helper file.
hwb.Close SaveChanges:=False
Application.ScreenUpdating = True
' Inform.
MsgBox "Split data exported.", vbInformation
End Sub
I am trying to skip all of the sheets that are"xlSheetHidden" or "xlSheetVeryHidden". I have recently started using VBA to help speed up processes at my work when python wasn't allowing for what was needed. I currently have the following code:
Sub Merge_Sheets()
Dim Work_Sheets() As String
ReDim Work_Sheets(Sheets.Count)
For i = 0 To Sheets.Count - 1
Work_Sheets(i) = Sheets(i + 1).Name
Next i
Sheets.Add.Name = "Combined Sheet"
Dim Column_Index As Integer
Column_Index = Worksheets(1).UsedRange.Cells(1, 1).Column
Dim Row_Index As Integer
Row_Index = 0
For i = 0 To Sheets.Count - 2
Set Rng = Worksheets(Work_Sheets(i)).UsedRange
Rng.Copy
Worksheets("Combined Sheet").Cells(Row_Index + 1, Column_Index).PasteSpecial Paste:=xlPasteValues
Row_Index = Row_Index + Rng.Rows.Count + 1
Next i
Application.CutCopyMode = False
End Sub
I have tried inserting If .Visible = xlSheetVisible Then but cannot get it to work.
I have also tried to make it work with:
For Each Sheets In ActiveWorkbook.Worksheets
If Sheet.Visible = xlSheetVisible Then
However this still doesn't seem to work, any help would be greatly appreciated.
You did not use the for each correctly. In your code you loop over sheets with the name Sheets, then in the loop you refer to Sheet
For Each Sheets In ActiveWorkbook.Worksheets
If Sheet.Visible = xlSheetVisible Then '// Doesn't work!
So you probaby only needed to fix up this variable naming:
For Each ws In ActiveWorkbook.Worksheets
If ws.Visible = xlSheetVisible Then
Or
For Each sht In ActiveWorkbook.Worksheets
If sht.Visible = xlSheetVisible Then
sht and ws are traditional vba coding variable names for sheet/worksheet objects. But you can use any name you like. However, not Sheets as a variable name, as that is already the name of the built-in Sheets collection.
Merge (Append) Visible Worksheets
Option Explicit
Sub MergeWorksheets()
' Define constants.
Const dName As String = "Combined Sheet"
Const dFirstCellAddress As String = "A1"
' Reference the workbook ('wb').
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Application.ScreenUpdating = False
' Delete the destination worksheet ('dws') if it exists.
Dim dws As Worksheet
On Error Resume Next
Set dws = wb.Worksheets(dName)
On Error GoTo 0
If Not dws Is Nothing Then
Application.DisplayAlerts = False
dws.Delete
Application.DisplayAlerts = True
End If
' Write the number of worksheets to a variable ('swsCount').
Dim swsCount As Long: swsCount = wb.Worksheets.Count
' Add the names of all the visible worksheets
' to an array ('WorksheetNames').
' A better choice here is to use a collection or a dictionary
' where it is not important to know the number of elements (items).
' But no harm done.
Dim WorksheetNames() As String: ReDim WorksheetNames(1 To swsCount)
Dim sws As Worksheet ' Current Source Worksheet
Dim n As Long ' Visible Worksheets Count(er)
For Each sws In wb.Worksheets
If sws.Visible = xlSheetVisible Then
n = n + 1
WorksheetNames(n) = sws.Name
End If
Next sws
If n = 0 Then
MsgBox "No visible worksheets found.", vbExclamation
Exit Sub
End If
' Resize the array to the actual number of found visible worksheets
' (not necessary since later we're looping with 'For n = 1 to n').
If n < swsCount Then ReDim Preserve WorksheetNames(1 To n)
' Add and reference a new worksheet, the destination worksheet ('dws').
' First sheet...
Set dws = wb.Worksheets.Add(Before:=wb.Sheets(1))
' ... or e.g. last sheet
'Set dws = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
dws.Name = dName ' rename
' Reference the first cell of the destination range ('dfCell').
Dim dfCell As Range: Set dfCell = dws.Range(dFirstCellAddress)
Dim srg As Range ' Current Source Range
Dim drg As Range ' Current Destination Range
For n = 1 To n
' Reference the source worksheet.
Set sws = wb.Worksheets(WorksheetNames(n))
' Reference the used range in the source worksheet.
Set srg = sws.UsedRange
' Reference the destination range, the destination cell
' resized by the number of rows and columns of the source range.
Set drg = dfCell.Resize(srg.Rows.Count, srg.Columns.Count)
' Write the values from the source range to the destination range.
drg.Value = srg.Value
' Reference the next destination first cell.
Set dfCell = dfCell.Offset(srg.Rows.Count)
Next n
Application.ScreenUpdating = True
' Inform to not wonder if the code has run or not.
MsgBox "Worksheets merged.", vbInformation
End Sub
I want to select particular columns and then paste this onto a particular sheet, if sheet exists then erase existing data and paste newly copied data. This should work in loop to be refreshed with new data entered in the main sheet.
My code creates the required sheet but pastes data into another new sheet.
Sub Datasort()
'The sheet with all the imported data columns must be active when this macro is run
Dim newSht As Worksheet, sSht As Worksheet, Hdrs As Variant, i As Long, Fnd As Range, Sheet_Name As String
Set sSht = Worksheets("all zip codes")
'Expand the array below to include all relevant column headers
Hdrs = Array("Country", "Zip codes", "GSS")
Application.ScreenUpdating = False
Sheet_Name = "Dataformatted"
Set newSht = Worksheets.Add(after:=sSht)
With sSht.UsedRange.Rows(1)
For i = LBound(Hdrs) To UBound(Hdrs)
Set Fnd = .Find(Hdrs(i), lookat:=xlWhole)
If Not Fnd Is Nothing Then
Intersect(Fnd.EntireColumn, sSht.UsedRange).Copy
newSht.Cells(1, i + 1).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
newSht.Cells(1, i + 1).PasteSpecial Paste:=xlPasteColumnWidths
End If
Next i
Application.CutCopyMode = False
End With
If (Sheet_Exists(Sheet_Name) = False) And (Sheet_Name <> "") Then
Worksheets.Add(after:=sSht).Name = Sheet_Name
End If
Application.ScreenUpdating = True
End Sub
Function Sheet_Exists(WorkSheet_Name As String) As Boolean
Dim newSht As Worksheet
Sheet_Exists = False
For Each newSht In ThisWorkbook.Worksheets
If newSht.Name = WorkSheet_Name Then
Sheet_Exists = True
End If
Next
End Function
(not tested), but you're adding sheet everytime it runs, so assuming everything else works fine, you should:
replace Set newSht = Worksheets.Add(after:=sSht) with below
if not Sheet_Exists(Sheet_Name) then Worksheets.Add(after:=sSht).Name = Sheet_Name
Set newSht = Worksheets(Sheet_Name)
and remove the following part
If (Sheet_Exists(Sheet_Name) = False) And (Sheet_Name <> "") Then
Worksheets.Add(after:=sSht).Name = Sheet_Name
End If
Copy Worksheet Columns
Option Explicit
Sub Datasort()
Const sName As String = "all zip codes"
Const dName As String = "Dataformatted"
Const dfcAddress As String = "A1"
Dim Headers As Variant: Headers = VBA.Array("Country", "Zip codes", "GSS")
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim srg As Range: Set srg = sws.UsedRange
Dim shrg As Range: Set shrg = srg.Rows(1)
Application.ScreenUpdating = False
Dim dws As Worksheet
On Error Resume Next
Set dws = wb.Worksheets(dName)
On Error GoTo 0
If dws Is Nothing Then
Set dws = wb.Worksheets.Add(After:=sws)
dws.Name = dName
Else
dws.UsedRange.Clear
End If
Dim dfCell As Range: Set dfCell = dws.Range(dfcAddress)
Dim scrg As Range
Dim hIndex As Variant
Dim c As Long
For c = 0 To UBound(Headers)
hIndex = Application.Match(Headers(c), shrg, 0)
If IsNumeric(hIndex) Then
Set scrg = srg.Columns(hIndex)
dfCell.Resize(scrg.Rows.Count).Value = scrg.Value
dfCell.EntireColumn.ColumnWidth = scrg.EntireColumn.ColumnWidth
Set dfCell = dfCell.Offset(, 1)
End If
Next c
Application.ScreenUpdating = True
MsgBox "Data formatted."
End Sub