copy all cell ranges - excel

Sub all_col()
Workbooks("xlsb file").Worksheets("sheet name").Range("A1:CR1048576").Copy_
Workbooks("xlsx file").Worksheets("sheet name").Range("A1")
How do I write more efficient code to copy all the cell ranges from one worksheet to another within different workbooks.instead of using "A1:CR1048576" is there a better way?

Try using the UsedRange property of the worksheet.
Sub all_col()
wb1.Worksheets("sheet name").UsedRange.Copy _
wb2.Worksheets("sheet name").Range("A1")
End Sub

Copy Worksheet In Closed Workbook to Worksheet in ThisWorkbook
The function is a sub converted to a function to return a boolean indicating whether it was successful i.e. whether no errors occurred.
You could classify this code as an 'import operation': the source workbook is closed, while the destination workbook contains the code. With 'a few changes', you could rewrite this code as an 'export operation': the destination workbook is closed and the source workbook contains the code. Looking at the file extensions, it looks like you needed the latter.
Option Explicit
Sub WsToWsInThisWorkbookTEST()
Dim GotCopied As Boolean: GotCopied = WsToWsInThisWorkbook( _
"C:\Test\Test.xlsx", "Sheet1", "A1", "Sheet1", "A1")
If Not GotCopied Then Exit Sub
'Continue with your code e.g.:
MsgBox "Worksheet got copied.", vbInformation
End Sub
Function WsToWsInThisWorkbook( _
ByVal SourceFilePath As String, _
Optional ByVal SourceSheetID As Variant, _
Optional ByVal SourceFirstCell As String = "A1", _
Optional ByVal DestinationSheetID As Variant = "Sheet1", _
Optional ByVal DestinationFirstCell As String = "A1") _
As Boolean
On Error GoTo ClearError
Const ProcName As String = "WsToWsInThisWorkbook"
' Source
If Len(Dir(SourceFilePath)) = 0 Then
MsgBox "Source file '" & SourceFilePath & "' not found.", vbCritical
Exit Function
End If
Dim swb As Workbook: Set swb = Workbooks.Open(SourceFilePath, True, True)
Dim sws As Worksheet: Set sws = swb.Sheets(SourceSheetID)
Dim srg As Range
With sws.UsedRange
Dim lcell As Range: Set lcell = .Cells(.Rows.Count, .Columns.Count)
Set srg = sws.Range(SourceFirstCell, lcell)
End With
' Destination.
Dim dwb As Workbook: Set dwb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = dwb.Sheets(DestinationSheetID)
Dim dfCell As Range: Set dfCell = dws.Range(DestinationFirstCell)
' Copy.
srg.Copy dfCell
WsToWsInThisWorkbook = True
ProcExit:
On Error Resume Next
If Not swb Is Nothing Then swb.Close SaveChanges:=False
On Error GoTo 0
Exit Function
ClearError:
MsgBox "Run-time error '" & Err.Number & "':" & vbLf & Err.Description, _
vbCritical, ProcName
Resume ProcExit
End Function

Most of the answers provided would work but UsedRange extends to formatting (see this epic thread] discussing best method to find last row).
If that were an issue, you could include these functions below your original macro and it will be the precise space to copy from:
Sub all_col()
Dim lastRow As Long, lastColumn As Long
With Workbooks("xlsb file").Worksheets("sheet name")
lastRow = FindLastRowInSheet(.Range("A1"))
lastColumn = FindLastColumnInSheet(.Range("A1"))
.Range("A1").Resize(lastRow, lastColumn).Copy_
Workbooks("xlsx file").Worksheets("sheet name").Range ("A1")
End With
End Sub
Function FindLastRowInRange(someColumns As Range) As Long
Const zFx = "=MAX(FILTER(ROW(????),NOT(ISBLANK(????)),0))"
Dim tRng As Range, i As Long, tRow As Long, pRng As Range
With someColumns.Worksheet
Set tRng = Intersect(someColumns.EntireColumn, .UsedRange)
For i = 1 To tRng.Columns.Count
Set pRng = Intersect(tRng.Columns(i), _
Range(.Rows(FindLastRowInRange + 1), .Rows(.Rows.Count)))
If Not pRng Is Nothing Then
tRow = .Evaluate(Replace(zFx, "????", _
pRng.Address, 1, -1))
If tRow > FindLastRowInRange Then _
FindLastRowInRange = tRow
End If
Next i
End With
End Function
Function FindLastRowInSheet(anywhereInSheet As Range) As Long
FindLastRowInSheet = FindLastRowInRange(anywhereInSheet.Worksheet.UsedRange)
End Function
Function findLastColumn(someRows As Range) As Long
Const zFx = "=MAX(FILTER(COLUMN(????),NOT(ISBLANK(????)),0))"
Dim tRng As Range, i As Long, tRow As Long, pRng As Range
With someRows.Worksheet
Set tRng = Intersect(.UsedRange, someRows.EntireRow)
For i = 1 To tRng.Rows.Count
Set pRng = Intersect(tRng.Rows(i), Range(.Rows(.Columns.Count), .Rows(findLastColumn + 1)))
If Not pRng Is Nothing Then
tRow = .Evaluate(Replace(zFx, "????", _
pRng.Address, 1, -1))
If tRow > findLastColumn Then _
findLastColumn = tRow
End If
Next i
End With
End Function
Function FindLastColumnInSheet(anywhereInSheet As Range) As Long
FindLastColumnInSheet = findLastColumn(anywhereInSheet.Worksheet.UsedRange)
End Function

Related

Creating worksheets and naming them with the values in a list/table [duplicate]

This question already has answers here:
Test or check if sheet exists
(23 answers)
Closed 2 months ago.
I am trying to create multiple worksheet in a workbook and name them based on a contents in a particular table. I am doing this as the list can be dynamic and might need to create more/less sheets depending on the requirement.
Sub CreateSheetsFromList()
Dim NewSheet As Worksheet
Dim x As Integer
Dim tbl As ListObject
Dim cell As Range
Application.ScreenUpdating = False
Set tbl = Worksheets("Sheet1").ListObjects("Table1")
For Each cell In tbl.DataBodyRange.Cells
If SheetExists(cell.Value) = False And cell.Value <> "" Then
Set NewSheet = Sheets.Add(after:=Sheets(Sheets.Count))
NewSheet.Name = cell.Value
End If
Next cell
Application.ScreenUpdating = True
End Sub
Function SheetExists(SheetName As String) As Boolean
Dim sht As Worksheet
On Error Resume Next
Set sht = ActiveWorkbook.Worksheets("Sheet1")
On Error GoTo 0
If Not sht Is Nothing Then SheetExists = True
Set sht = Nothing
End Function
Unable to get any kind of results. Please let me know if there is a way to do this in an optimized manner
You have to use the passed variable to check - not a fixed value ("Sheet1"):
Function SheetExists(SheetName As String) As Boolean
Dim sht As Worksheet
On Error Resume Next
'Use the passed SheetName to test for
Set sht = ActiveWorkbook.Worksheets(SheetName)
On Error GoTo 0
If Not sht Is Nothing Then SheetExists = True
End Function
Add Sheets From Excel Table (ListObject)
Utilization
Sub AddSheetsFromListObjectTEST()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
AddSheetsFromListObject wb, "Sheet1", "Table1", 1
End Sub
The Method
Sub AddSheetsFromListObject( _
ByVal wb As Workbook, _
ByVal WorksheetID As Variant, _
ByVal ListObjectID As Variant, _
ByVal ListColumnID As Variant)
Const PROC_TITLE As String = "Create Sheets From ListObject"
On Error GoTo ClearError
Dim sws As Worksheet: Set sws = wb.Sheets(WorksheetID)
Dim slo As ListObject: Set slo = sws.ListObjects(ListObjectID)
Dim slc As ListColumn: Set slc = slo.ListColumns(ListColumnID)
Dim srg As Range: Set srg = slc.DataBodyRange
Dim dws As Worksheet, sCell As Range, dName As String, NotRenamed As Boolean
For Each sCell In srg.Cells
dName = CStr(sCell.Value)
If dws Is Nothing Then
Set dws = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
End If
On Error GoTo RenameError
dws.Name = dName
On Error GoTo ClearError
If NotRenamed Then NotRenamed = False Else Set dws = Nothing
Next sCell
If Not dws Is Nothing Then
Application.DisplayAlerts = False
dws.Delete
Application.DisplayAlerts = True
End If
ProcExit:
Exit Sub
RenameError:
'Debug.Print "Name = """ & dName & """" & vbLf & Left(Err.Description, 48)
NotRenamed = True
Resume Next
ClearError:
MsgBox "Run-time error '" & Err.Number & "':" & vbLf & vbLf _
& Err.Description, vbCritical, PROC_TITLE
Resume ProcExit
End Sub

Find() returns "object variable or with block variable not set"

This block of code was working fine but I deleted some lines above Find() that broke it. Any ideas?
Sub CopySheet()
Dim TotalRow As Integer
Set NurselineBook = ThisWorkbook
TotalRow = Range("$C:$C").Find(What:="Grand Total", LookIn:=xlValues, LookAt:=xlWhole).Row
Range("A1:L" & TotalRow).Select
Range("Ah1").Activate
Selection.CopyPicture Appearance:=xlScreen, Format:=xlBitmap
MsgBox "Dashboard Copied"
End Sub
Sub CopyTable()
Const wsName As String = "Sheet1"
Const ColumnsAddress As String = "A:L"
Const FirstRow As Long = 1
Const CriteriaColumn As Long = 3
Const gtString As String = "Grand Total"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
Dim srg As Range
With ws.Columns(ColumnsAddress)
Set srg = .Resize(ws.Rows.Count - FirstRow + 1).Offset(FirstRow - 1)
End With
Dim gtcell As Range: Set gtcell = srg.Columns(CriteriaColumn) _
.Find(gtString, , xlValues, xlWhole, , xlPrevious)
If gtcell Is Nothing Then
MsgBox "Could not find '" & gtString & "'.", vbCritical
Exit Sub
End If
Dim drg As Range
Set drg = srg.Resize(gtcell.Row - FirstRow + 1)
drg.CopyPicture Appearance:=xlScreen, Format:=xlBitmap
MsgBox "Dashboard Copied", vbInformation
End Sub

Copy a column by name from multiple Excel files which are saved in a specific folder and save it in csv

I'm trying to copy a column from all the Excel files(.xls) saved in a specific folder and append to a text file.
Selecting the column should be based on the column name, as the column number varies for every Excel file.
How can I create the script with this condition?
Stack Columns
This will copy the columns' values to a new (destination) workbook and save the workbook in the same folder as the folder of the workbook containing this code (Thisworkbook). The new workbook is named after the header (Name.csv).
An improvement would be to write the values to a data structure (array, dictionary, or array list) and afterward to write its values to a text file in one go without ever having a destination workbook.
Adjust the values in the constants section.
Option Explicit
Sub StackColumns()
' Needs 'RefWorksheet', 'RefFirstOccurrenceInRow' and 'RefColumnDataRange'
Const ProcTitle As String = "Stack Columns"
' Source
Const sFolderPath As String = "C:\Test\"
Const sFilePattern As String = "*.xls*"
Const swsName As String = "Sheet1"
Const sHeader As String = "Name"
Const shRow As Long = 1
' Destination
Dim dFolderPath As String: dFolderPath = ThisWorkbook.Path & "\"
Dim dBaseName As String: dBaseName = sHeader
Dim sFileName As String: sFileName = Dir(sFolderPath & sFilePattern)
If Len(sFileName) = 0 Then
MsgBox "No files found.", vbCritical, ProcTitle
Exit Sub
End If
Dim swb As Workbook
Dim sws As Worksheet
Dim shCell As Range ' Header Cell
Dim scdtrg As Range ' Column Data Range (no headers)
Dim dwb As Workbook
Dim dws As Worksheet
Dim dCell As Range
Dim IsDestinationWorkbookAdded As Boolean
Application.ScreenUpdating = False
Do Until Len(sFileName) = 0
Set swb = Workbooks.Open(sFolderPath & sFileName)
Set sws = RefWorksheet(swb, swsName)
If Not sws Is Nothing Then ' worksheet found
Set shCell = RefFirstOccurrenceInRow(sws.Rows(shRow), sHeader)
If Not shCell Is Nothing Then ' header found
Set scdtrg = RefColumnDataRange(shCell)
If Not scdtrg Is Nothing Then ' found data in Column Data Range
If Not IsDestinationWorkbookAdded Then ' not yet added
Set dwb = Workbooks.Add(xlWBATWorksheet)
Set dws = Worksheets(1)
Set dCell = dws.Range("A1")
IsDestinationWorkbookAdded = True
'Else ' already added
End If
dCell.Resize(scdtrg.Rows.Count).Value = scdtrg.Value
Set dCell = dCell.Offset(scdtrg.Rows.Count)
Set scdtrg = Nothing
'Else ' no data in Column Data Range
End If
Set shCell = Nothing
'Else ' header not found
End If
Set sws = Nothing
'Else ' worksheet not found
End If
swb.Close False
sFileName = Dir
Loop
If Not dwb Is Nothing Then
Application.DisplayAlerts = False ' overwrite without confirmation
dwb.SaveAs dFolderPath & dBaseName & ".csv", xlCSV
Application.DisplayAlerts = True
'dwb.FollowHyperlink dFolderPath ' explore the Destination Path
'dwb.Close
End If
Application.ScreenUpdating = True
MsgBox "Columns stacked.", vbInformation, ProcTitle
End Sub
Function RefWorksheet( _
ByVal wb As Workbook, _
ByVal WorksheetName As String) _
As Worksheet
On Error Resume Next
Set RefWorksheet = wb.Worksheets(WorksheetName)
On Error GoTo 0
End Function
Function RefFirstOccurrenceInRow( _
ByVal RowRange As Range, _
ByVal SearchString As String) _
As Range
On Error GoTo ClearError
With RowRange.Rows(1)
Set RefFirstOccurrenceInRow _
= .Find(SearchString, .Cells(.Cells.Count), xlFormulas, xlWhole)
End With
ProcExit:
Exit Function
ClearError:
Resume ProcExit
End Function
Function RefColumnDataRange( _
ByVal HeaderCell As Range) _
As Range
On Error GoTo ClearError
With HeaderCell.Cells(1)
With .Resize(.Worksheet.Rows.Count - .Row).Offset(1)
Dim lCell As Range
Set lCell = .Find("*", , xlFormulas, , , xlPrevious)
Set RefColumnDataRange = .Resize(lCell.Row - .Row + 1)
End With
End With
ProcExit:
Exit Function
ClearError:
Resume ProcExit
End Function

Checkbox to copy selected cells only and paste to another worksheet

I'm not very advanced in this however I'm hoping to obtain some direction. I'm currently running the following VBA:
Private Sub CommandButton1_Click()
If (CheckBox1.Value = True) Then
ActiveSheet.Range("B13:E18").Copy
End If
If (CheckBox2.Value = True) Then
ActiveSheet.Range("B20:E25").Copy
End If
If (CheckBox3.Value = True) Then
ActiveSheet.Range("B27:E32").Copy
End If
If (CheckBox4.Value = True) Then
ActiveSheet.Range("B34:E39").Copy
End If
'copy the chunk above for more check boxes
End Sub
However, it only ends up copying the last selected checkbox instead of multiple cells at once. What am I missing in order to copy only selected cells per a checkbox and copying them over to another worksheet within the same workbook?
Here's a crude but working example:
Public Sub CommandButton1_Click()
Dim rgCopy As Range
With ActiveSheet
If CheckBox1 Then
Set rgCopy = .Range("B13:E18")
End If
If CheckBox2 Then
If rgCopy Is Nothing Then
Set rgCopy = .Range("B20:E25")
Else
Set rgCopy = Union(rgCopy, .Range("B20:E25"))
End If
End If
If CheckBox3 Then
If rgCopy Is Nothing Then
Set rgCopy = .Range("B27:E32")
Else
Set rgCopy = Union(rgCopy, .Range("B27:E32"))
End If
End If
If CheckBox4 Then
If rgCopy Is Nothing Then
Set rgCopy = .Range("B34:E39")
Else
Set rgCopy = Union(rgCopy, .Range("B34:E39"))
End If
End If
End With
If Not rgCopy Is Nothing Then
rgCopy.Copy
Else
MsgBox "nothing selected message"
End If
End Sub
Copy Ranges Depending on Checkboxes' Value
Standard Module e.g. Module1
Option Explicit
Sub CopyChkBoxConsecutiveRanges(ByVal chkBoxes As Variant)
' Source
Const sName As String = "Sheet1"
Const sfrgAddress As String = "B13:E18"
Const sGap As Long = 1
' Destination
Const dName As String = "Sheet2"
Const dfCellAddress As String = "A2"
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook
' Source
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim srg As Range: Set srg = RefChkBoxConsecutiveRanges( _
sws.Range(sfrgAddress), chkBoxes, sGap)
'Destination
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfCell As Range: Set dfCell = dws.Range(dfCellAddress)
' Copy
If Not srg Is Nothing Then
srg.Copy dfCell
End If
End Sub
Function RefChkBoxConsecutiveRanges( _
ByVal sfrg As Range, _
ByVal chkBoxes As Variant, _
Optional ByVal sGap As Long = 0, _
Optional ByVal SearchOrder As XlSearchOrder = xlByRows) _
As Range
' Needs `RefCombinedRange`.
Dim sws As Worksheet: Set sws = sfrg.Worksheet
Dim srOffset As Long
srOffset = IIf(SearchOrder = xlByRows, sfrg.Rows.Count + sGap, 0)
Dim scOffset As Long
scOffset = IIf(SearchOrder = xlByRows, 0, sfrg.Columns.Count + sGap)
Dim scrg As Range: Set scrg = sfrg
Dim srg As Range
Dim n As Long
For n = LBound(chkBoxes) To UBound(chkBoxes)
If chkBoxes(n) Then
Set srg = RefCombinedRange(srg, scrg)
End If
Set scrg = scrg.Offset(srOffset, scOffset)
Next n
If Not srg Is Nothing Then
Set RefChkBoxConsecutiveRanges = srg
End If
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to a range combined from two ranges.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefCombinedRange( _
ByVal CombinedRange As Range, _
ByVal AddRange As Range) _
As Range
If CombinedRange Is Nothing Then
Set RefCombinedRange = AddRange
Else
Set RefCombinedRange = Union(CombinedRange, AddRange)
End If
End Function
Userform Module e.g. UserForm1
Private Sub CommandButton1_Click()
Dim chkBoxes As Variant
chkBoxes = Array(CheckBox1, CheckBox2, CheckBox3, CheckBox4) ' add more
CopyChkBoxConsecutiveRanges chkBoxes
End Sub

Why does this not create a combobox?

Sub Auto_Open()
Dim ComboBox2 As Object
Dim ws As Worksheet
Dim rng As Range
Const cCount As Long = 2
Set ws = ActiveSheet(1)
With ws
Set rng = .Range("H10")
Set ComboBox2 = .Shapes.AddFormControl(xlDropDown, _
Left:=rng.Left, _
Top:=rng.Top, _
Width:=rng.Width, _
Height:=rng.Height)
With ComboBox2
.ControlFormat.DropDownLines = 100
.Name = "myCombo"
End With
With Worksheets(5)
Dim erg As Range: Set erg = .Range("D6", .Range("D" & .Rows.Count) _
.End(xlUp)).Resize(, cCount)
Worksheets(1).ComboBox2.ColumnCount = cCount
Worksheets(1).ComboBox2.List = erg.Value
End With
End Sub
This code is in the workbook.
I am trying to create a combobox when someone opens this file and then have it to be populated from worsheet 5.
Its not happening, nothing is created and im also not getting any errors.
Try using Workbook_Open event instead of Auto_Open event (it exist for backwards compatibility), the code should be placed in ThisWorkbook object.
Private Sub Workbook_Open()
Dim ComboBox2 As Object
Dim ws As Worksheet
Dim rng As Range
Const cCount As Long = 2
Set ws = ActiveSheet 'Avoid using ActiveSheet, replace this with the worksheet name instead
With ws
Set rng = .Range("H10")
Set ComboBox2 = .Shapes.AddFormControl(xlDropDown, _
Left:=rng.Left, _
Top:=rng.Top, _
Width:=rng.Width, _
Height:=rng.Height)
End With
With ComboBox2
.ControlFormat.DropDownLines = 100
.Name = "myCombo"
End With
With Worksheets(5)
Dim erg As Range
Set erg = .Range("D6", .Range("D" & .Rows.Count) _
.End(xlUp)).Resize(, cCount)
End With
With Worksheets(1).ComboBox2
.ColumnCount = cCount
.List = erg.Value
End With
End Sub

Resources