Excel VBA copying specific columns - vba

I have the following VBA code for excel
Dim k As Integer, z As Integer
Dim sourceSht As Worksheet
Dim destSht As Worksheet
z = 0
Set sourceSht = Sheets("sheet1")
Set destSht = Sheets("sheet2")
DoEvents
For k = 1 To 5000
If k < 3 Or (k - 1) Mod 3 <> 0 Then
z = z + 1
sourceSht.Columns(k).Copy destSht.Columns(z)
End If
Next
This code was working perfectly for rows (changed this part"sourceSht.Columns(k).Copy destSht.Columns(z)").
but I can not make it work for columns. I want excel to copy the first 2 columns then skip the third one, then copy 2 again, skip one and etc... can somebody help me and explain what am I doing wrong?

I'm going to ignore the use of mod and do a Step 3 with the loop:
Dim i as Long, j as Long
For i = 1 to 5000 Step 3
With sourceSht
If j = 0 Then
j = 1
Else
j = j + 2 'Copying 2 columns over, so adding 2 each time
End If
.Range(.Columns(i),.Columns(i+1)).Copy destSht.Range( destSht.Columns(j), destSht.Column(j+1))
End With
Next i
Something like that should do it for you

Alternate:
Sub tgr()
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim rCopy As Range
Dim rLast As Range
Dim LastCol As Long
Dim i As Long
Set wsSource = ActiveWorkbook.Sheets("Sheet1")
Set wsDest = ActiveWorkbook.Sheets("Sheet2")
On Error Resume Next
Set rLast = wsSource.Cells.Find("*", wsSource.Range("A1"), xlFormulas, , xlByColumns, xlPrevious)
On Error GoTo 0
If rLast Is Nothing Then Exit Sub 'No data
LastCol = rLast.Column
Set rCopy = wsSource.Range("A:B")
For i = 4 To LastCol Step 3
Set rCopy = Union(rCopy, wsSource.Columns(i).Resize(, 2))
Next i
rCopy.Copy wsDest.Range("A1")
End Sub

Try this (use count for the number of time you need to copy columns, t for the first columns you need to copy):
Sub copy_columns()
t = 1
Count = 1
Do Until Count = 10
Range(Columns(t), Columns(t + 1)).Copy
Cells(1, t + 3).Select
Selection.PasteSpecial Paste:=xlPasteValues
t = t + 3
Count = Count + 1
Loop
End Sub

Related

Excel VBA Macro to add a blank row when the value in column A is 1

I wanted to add a row in excel vba when ever the value in column A is 1, here is the code I wrote, but this returns a "subscript out of range error". What am I doing wrong?
Sub InsertRow()
Dim Col As Variant
Dim BlankRows As Long
Dim LastRow As Long
Dim R As Long
Dim StartRow As Long
Application.ScreenUpdating = False
Col = "A"
StartRow = 1
LastRow = 20
Worksheets("Sheet1").Activate
For R = StartRow To LastRow
If Cells(R, Col) = 1 Then
Cells(R, Col).EntireRow.Insert Shift:=xlDown
End If
Next R
Application.ScreenUpdating = True
End Sub
Code below tested and works.
With Worksheets("Sheet1")
Dim cntr as Long
For cntr = 20 to 5 Step - 1
If .Cells(cntr, 1) = 1 Then .cells(cntr,1).EntireRow.Insert Shift:=xlDown
Next
End With
Sub InsertRow()
Dim Col As Variant
Dim BlankRows As Long
Dim LastRow As Long
Dim R As Long
Dim StartRow As Long
Application.ScreenUpdating = False
Col = "A"
StartRow = 1
LastRow = 20
Worksheets("Sheet1").Activate
R = StartRow
Do While R <= LastRow
If Cells(R, Col) = 1 Then
Cells(R, Col).EntireRow.Insert Shift:=xlDown
R = R + 1
LastRow = LastRow + 1
End If
R = R + 1
Loop
Application.ScreenUpdating = True
End Sub
Note the setting of the value of R in the loop, as you are shifting the rows down, you are continually checking the same value and therefore adding a row each time so we need to increment R by 1 to skip past the 1 we just checked.
We also need to change the endpoint as we are pushing values past Row 20 by inserting so we also increment the LastRow variable. We cannot do this in a for loop in VBA, the for loop will terminate at 20 so I have changed to a while loop
As per the comment below, working backwards from 20 is far more elequent but since I didn't think of that I haven't put it in here :)

Delete entire Row with zeroes apply to all worksheets

I have VBA code that works to delete entire row when there is an absolute zero value in one a cell column but, I am not able to figure out how to update code to apply to all worksheets (there are 20 Sheets in my workbook):
Can someone help with syntax how to update this code to apply to all worksheets in the workbook.
Sub IfandthenDelete_Button3_Click()
Dim lRow As Long
Dim i As Long
lRow = 3000
Application.ScreenUpdating = False
For i = lRow To 1 Step -1
If Cells(i, 1) = 0 Then
Rows(i).Delete
End If
Next
Application.ScreenUpdating = False
End Sub
You need one more for loop for that.
Sub WorksheetLoop()
Dim wsCount As Integer
Dim j As Integer
Dim lRow As Long
Dim i As Long
lRow = 3000
wsCount = ActiveWorkbook.Worksheets.Count
For j = 1 To wsCount
For i = lRow To 1 Step -1
If ActiveWorkbook.Worksheets(j).Cells(i, 1) = 0 Then
ActiveWorkbook.Worksheets(j).Rows(i).Delete
End If
Next
Next j
End Sub

Excel VBA - Need to delete rows where cell values in column B where reference errors are populated

I have a loop towards the bottom of my code that successfully loops through my data and clears out all rows where Column H = 0.
However, there are several cells in column B displaying #REF!. I would also like this loop to delete those rows in the same manner as it does the 0s in column H.
I think my issue is not knowing how to reference those types of errors. Treating #REF! like a string doesn't appear to be working.
Thank you!
Sub test()
Dim currentSht As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Dim startCell As Range
Dim r As Integer
Set startCell = Sheets("Sheet1").Range("A1")
Set currentSht = ActiveWorkbook.Sheets("Sheet1")
lastRow = startCell.SpecialCells(xlCellTypeLastCell).Row '<~~ Not sure why, but do not use "Set" when defining lastRow
lastCol = startCell.SpecialCells(xlCellTypeLastCell).Column
For r = 1 To lastRow Step -1
If currentSht.Cells(r, "H").Value = 0 Or currentSht.Cells(r, "B").Text = "#REF!" Then
Rows(r).Select
Selection.EntireRow.Delete
End If
Next r
currentSht.Range(startCell, currentSht.Cells(lastRow, lastCol)).Select
End Sub
I think I see your problem:
For r = 1 To lastRow Step -1
Change that line to
For r = lastrow to 1 Step -1
How about this code:
Sub Delete0()
Dim F As Integer
Dim Y As Integer
Dim RngCount As Range
Set RngCount = ActiveSheet.Range("H:H")
Y = Application.WorksheetFunction.CountA(RngCount)
For F = Y To 1 Step -1
If IsError(ActiveSheet.Range("H" & F)) Then
ActiveSheet.Rows(F).EntireRow.Delete
ElseIf ActiveSheet.Range("H" & F).Value = 0 Then
ActiveSheet.Rows(F).EntireRow.Delete
End If
Next F
End Sub

Looping through range using variables (rows and columns)

I'm writing a simple formatting macro to alternate the row color for a table in Excel.
I want this macro to be able to format any size table (no matter row/column size).
For example, I want the macro to work when I have a chart with 6 rows 4 columns, or 4 rows 5 columns, or 9 rows 10 columns, etc.
Here's the code I have so far - but I'm getting a runtime error.
If ActiveSheet Is Nothing = False Then
Set MyWS = ActiveWorkbook.ActiveSheet
lastCol = MyWS.UsedRange.Columns.Count + 1
lastRow = MyWS.UsedRange.Rows.Count + 1
For Each Cell In Range(lastRow, lastCol) ''change range accordingly
If Cell.Row Mod 2 = 1 Then
Cell.Interior.ColorIndex = 15 ''color to preference
Else
Cell.Interior.ColorIndex = 14 ''color to preference or remove
End If
Next Cell
End If
I've tried multiple versions of the Range - having the column var come first, having an '&' instead of a comma, etc.
If I use just Range("A1:A" & lastRow), it'll work but just for the data in column A.
I would need it to span across all columns in the chart.
If the tables are all starting from cell A1, change your for statement to:
For Each Cell In Range("A1", Cells(lastRow, lastCol)) ''change range accordingly
Though also, the way your for loop works is that it is changing every cell. It can be optimized to color the row up to the last column at once.
If ActiveSheet Is Nothing = False Then
Set MyWS = ActiveWorkbook.ActiveSheet
lastCol = MyWS.UsedRange.Columns.Count + 1
lastRow = MyWS.UsedRange.Rows.Count + 1
Dim i As Integer
For i = 1 To lastRow
If i Mod 2 = 1 Then
Range("A" & i, Cells(i, lastcol)).Interior.ColorIndex = 15
Else
Range("A" & i, Cells(i, lastcol)).Interior.ColorIndex = 14
End If
Next i
End If
Try this:
Dim r As Range
For Each r In MyWs.UsedRange.Rows
If r.Row Mod 2 = 1 Then
r.Interior.ColorIndex = 15
Else
r.Interior.ColorIndex = 14
End If
Next r
Always good to include Option Explicit in your code modules. Try the following:
Option Explicit
Sub test()
Dim MyWS As Excel.Worksheet
Dim objRow As Excel.Range
Dim lastCol As Long
Dim lastRow As Long
Dim lngRow As Long
If ActiveSheet Is Nothing = False Then
Set MyWS = ActiveWorkbook.ActiveSheet
lastCol = MyWS.UsedRange.Columns.Count + 1
lastRow = MyWS.UsedRange.Rows.Count + 1
For lngRow = 1 To lastRow
Set objRow = MyWS.Range(MyWS.Cells(lngRow, 1), MyWS.Cells(lngRow, lastCol))
If lngRow Mod 2 = 1 Then
objRow.Interior.ColorIndex = 15 'color to preference
Else
objRow.Interior.ColorIndex = 14 'color to preference or remove
End If
Next lngRow
End If
End Sub

Move certain row of data into column

If I have all data in one very long column like this:
A
B
C
1
2
3
D
E
F
4
5
6
G
H
I
7
8
9
Is it possible to move data like this?
Column1 Column2 Column3 Column4 Column5 Column6
A B C 1 2 3
D E F 4 5 6
G H I 7 8 9
I tried paste special+transpose , but I have more than 10 thousands records , so it will take me too much time in using this method.
I'm new in excel and macro , thank you very much.
Edit:
I even tried to transpose all data into many columns then select the column I want to make them all into one column with this macro:
Sub OneColumn()
' Jason Morin as amended by Doug Glancy
' http://makeashorterlink.com/?M19F26516
''''''''''''''''''''''''''''''''''''''''''
'Macro to copy columns of variable length
'into 1 continuous column in a new sheet
''''''''''''''''''''''''''''''''''''''''''
Dim from_lastcol As Long
Dim from_lastrow As Long
Dim to_lastrow As Long
Dim from_colndx As Long
Dim ws_from As Worksheet, ws_to As Worksheet
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set ws_from = ActiveWorkbook.ActiveSheet
from_lastcol = ws_from.Cells(1, Columns.Count).End(xlToLeft).Column
'Turn error checking off so if no "AllData" trying to delete doesn't generate Error
On Error Resume Next
'so not prompted to confirm delete
Application.DisplayAlerts = False
'Delete if already exists so don't get error
ActiveWorkbook.Worksheets("AllData").Delete
Application.DisplayAlerts = True
'turn error checking back on
On Error GoTo 0
'since you refer to "AllData" throughout
Set ws_to = Worksheets.Add
ws_to.Name = "AllData"
For from_colndx = 1 To from_lastcol
from_lastrow = ws_from.Cells(Rows.Count, from_colndx).End(xlUp).Row
'If you're going to exceed 65536 rows
If from_lastrow + ws_to.Cells(Rows.Count, 1).End(xlUp).Row <= 65536 Then
to_lastrow = ws_to.Cells(Rows.Count, 1).End(xlUp).Row
Else
MsgBox "This time you've gone to far"
Exit Sub
End If
ws_from.Range(ws_from.Cells(1, from_colndx), ws_from.Cells(from_lastrow, _
from_colndx)).Copy ws_to.Cells(to_lastrow + 1, 1)
Next
' this deletes any blank rows
ws_to.Columns(1).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
But it will just join all column into one but not the column selected.
For Remou reference:
Here is the output:
A D G
B E H
C F I
1 4 7
2 5 8
3 6 9
You can look at something in these lines:
Sub TransposeColumn()
Dim rng As Range
Dim ws As Worksheet
Set rng = Worksheets("Input").UsedRange
Set ws = Worksheets("Output")
j = 1
k = 1
For i = 1 To rng.Rows.Count
If rng.Cells(i, 1) = vbNullString Then
j = j + 1
k = 1
Else
''ws.Cells(k, j) = rng.Cells(i, 1)
''EDIT
ws.Cells(j, k) = rng.Cells(i, 1)
k = k + 1
End If
Next
End Sub
This is how I do the same thing... it creates the new table in column C over...based on your example that there is a blank cell between each group of data:
Sub TransposeGroups()
Dim RNG As Range, Grp As Long, NR As Long
Set RNG = Range("A:A").SpecialCells(xlConstants)
NR = 1
For Grp = 1 To RNG.Areas.Count
RNG.Areas(Grp).Copy
Range("C" & NR).PasteSpecial xlPasteAll, Transpose:=True
NR = NR + 1
Next Grp
End Sub
This should work for any length of data and "groups" of up to 8500 within the data.
This also uses the AREAS method, but this overcomes the groups limitation by using subgroups, so it should work with any size dataset.
Sub TransposeGroups2()
'Uses the AREAS method and will work on any size data set
'overcomes the limitation of areas by working in subgroups
Dim RNG As Range, rngSTART As Range, rngEND As Range
Dim LR As Long, NR As Long, SubGrp As Long, Itm As Long
LR = Range("A" & Rows.Count).End(xlUp).Row
NR = 1
SubGrp = 1
Set rngEND = Range("A" & SubGrp * 10000).End(xlUp)
Set RNG = Range("A1", rngEND).SpecialCells(xlConstants)
Do
For Itm = 1 To RNG.Areas.Count
RNG.Areas(Itm).Copy
Range("C" & NR).PasteSpecial xlPasteAll, Transpose:=True
NR = NR + 1
Next Itm
If rngEND.Row = LR Then Exit Do
Set rngSTART = rngEND.Offset(1)
SubGrp = SubGrp + 1
Set rngEND = Range("A" & (SubGrp * 10000)).End(xlUp)
Set RNG = Range(rngSTART, rngEND).SpecialCells(xlConstants)
Loop
End Sub