Limitation for Transpose Function - excel

I am trying to find a workaround as transpose will not fit my data size, which is giving me an error. What do I added in right before the end of the loop -before the Next- to paste the data on a new sheet? Will this slow down the macro it the output is 100,000 lines
After reviewing the code I realized that if I make the range to a certain number it works and +1 row after that it errors out. Turns out transpose is to blame.
For Q = 1 To Data + 1
n = n + 1
ReDim Preserve var(1 To 3, 1 To n)
var(1, n) =
For R = 2 To 6
var(r, n) =
Next R
var(1, n) =
var(2, n) =
Next Q
Next_Loop:
Next P
With this workbook.sheet1
If Q>= 2 Then
.Range("a1").Resize(n, 6) = WorksheetFunction.Transpose(var)
End If
The result should be instead of pasting all the data at the end, it pastes the data after each iteration (unless it slows down the macro). Next iteration would be below the previous line of data. etc.
thank you for any insight

Here is an option for you to try.
Sub LongColumnToAFewColumns()
Dim wsF As Worksheet, WST As Worksheet
Dim rf As Range, rT As Range
Dim R As Long, j As Integer
' initialize
Set wsF = ActiveSheet
Set WST = Sheets.Add
WST.Name = "Results"
j = 1
For R = 1 To wsF.Cells(Rows.Count, 1).End(xlUp).Row Step 65536
wsF.Cells(R, 1).Resize(65536).Copy
WST.Cells(j, 1).PasteSpecial xlPasteValues
WST.Cells(j, 1).PasteSpecial xlPasteValues
j = j + 1
Next R
End Sub
If you want one long column cut into a few long rows, then use this.
Sub LongColumnToAFewRows()
Dim wsF As Worksheet, WST As Worksheet
Dim rf As Range, rT As Range
Dim R As Long, j As Integer
' initialize
Set wsF = ActiveSheet
Set WST = Sheets.Add
WST.Name = "Results2"
j = 1
For R = 1 To wsF.Cells(Rows.Count, 1).End(xlUp).Row Step Columns.Count
wsF.Cells(R, 1).Resize(Columns.Count).Copy
WST.Cells(j, 1).PasteSpecial xlPasteValues, Transpose:=True
j = j + 1
Next R
End Sub
One more for consideration.
Sub testing()
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim ptrSource As Long
Dim ptrDest As Long
Dim colDest As Long
Set wsDest = Sheets.Add
wsDest.Name = "Results"
Set wsSource = Worksheets("Sheet1")
colDest = 1
ptrSource = 1
ptrDest = 1
Do While Len(wsSource.Cells(ptrSource, 1)) > 0
wsDest.Cells(ptrDest, colDest) = wsSource.Cells(ptrSource, 1)
If colDest = Columns.Count Then
colDest = 0
ptrDest = ptrDest + 1
End If
ptrSource = ptrSource + 1
colDest = colDest + 1
Loop
Set wsDest = Nothing
Set wsSource = Nothing
End Sub

Related

Perform average and sum calculations on Several sheets in my workbook

I have several sheets with numeric data in columns B up to Column I, and and dates in column J. I've found and edited this macro which I thought would give me the averages and the totals of each column for all sheets. However all it seems to do is give me the total for Column I on each sheet. I'm quite new to VBA and I've got into a bit of a mess with this. I'm wondering if I'm making a basic mistake somewhere?
Sub CalcOnSheets2()
Application.ScreenUpdating = False
Dim Row As Integer
Dim lastrow As Long
Dim ActiveWorksheet As Long
Dim ThisWorksheet As Long
Dim N As Integer
Dim x As Integer
x = Sheets.Count
For N = 2 To x
lastrow = Sheets(N).Cells(Rows.Count, "D").End(xlUp).Row
Sheets(N).range("a1:J" & lastrow + 3).Columns.AutoFit
If lastrow > 1 Then
For Row = 3 To lastrow
Sheets(N).range("B1:J" & lastrow + 3).NumberFormat = "£#,##0.00);(£#,##0.00)"
Next
Dim r As range, j As Long, k As Long, z As Long
j = Sheets(N).range("B2").End(xlToRight).Column
For k = 2 To j - 1
Set r = Sheets(N).range(Sheets(N).Cells(1, k), Sheets(N).Cells(1, k).End(xlDown))
r.End(xlDown).Offset(2, 0) = WorksheetFunction.Sum(r)
r.End(xlDown).Offset(3, 0) = WorksheetFunction.Average(r)
Next k
Else
MsgBox ("There is no data at column D")
End If
Application.ScreenUpdating = True
range("A1").Select
Next N
End Sub
I fixed a few things. Your for loops weren't closing out correctly. Keep going on learning VBA! There are definitely easier ways to lick this problem, but hey this one seems to work so what the heck. Here is the updated code, hopefully it works for you...
Sub CalcOnSheets2()
Application.ScreenUpdating = False
Dim Row As Integer
Dim lastrow As Long
Dim ActiveWorksheet As Long
Dim ThisWorksheet As Long
Dim N As Integer
Dim r As Range, j As Long, k As Long, z As Long
Dim x As Integer
x = Sheets.Count
For N = 2 To x
lastrow = Sheets(N).Cells(Rows.Count, "D").End(xlUp).Row
Sheets(N).Range("a1:J" & lastrow + 3).Columns.AutoFit
If lastrow > 1 Then
For Row = 3 To lastrow
Sheets(N).Range("B1:I" & lastrow + 3).NumberFormat = "£#,##0.00;(£#,##0.00)"
Next
j = Sheets(N).Range("B2").End(xlToRight).Column
For k = 2 To j - 1
Set r = Sheets(N).Range(Sheets(N).Cells(1, k), Sheets(N).Cells(1, k).End(xlDown))
r.End(xlDown).Offset(2, 0) = WorksheetFunction.Sum(r)
r.End(xlDown).Offset(3, 0) = WorksheetFunction.Average(r)
Next k
Else
MsgBox ("There is no data at column D")
End If
Range("A1").Select
Next N
Application.ScreenUpdating = True
End Sub
A little simplified:
Sub CalcOnSheets2()
Dim lastrow As Long
Dim ws As Worksheet
Dim k As Long, r As Range
Application.ScreenUpdating = False
For Each ws In ActiveWorkbook.Worksheets
lastrow = ws.Cells(Rows.Count, "D").End(xlUp).Row
ws.Range("A1:J" & lastrow + 3).Columns.AutoFit
If lastrow > 1 Then
ws.Range("B1:J" & lastrow + 3).NumberFormat = "£#,##0.00;(£#,##0.00)"
For k = 2 To ws.Range("B2").End(xlToRight).Column - 1
Set r = ws.Range(ws.Cells(k, 1), ws.Cells(k, lastrow))
ws.Cells(lastrow + 2, k) = WorksheetFunction.Sum(r)
ws.Cells(lastrow + 3, k) = WorksheetFunction.Average(r)
Next k
Else
MsgBox ("There is no data at column D")
End If
Next ws
Application.ScreenUpdating = True
End Sub

change to dynamic vba

i want to have rows from one worsheet copy to another worksheet based on a specific text, i need it to run as new data will be added daily, i am using this code now but it needs to be run after inputting data.
Sub CopyYes()
Dim c As Range
Dim j As Integer
Dim Source As Worksheet
Dim Target As Worksheet
Set Source = ActiveWorkbook.Worksheets("MAINGANG")
Set Target = ActiveWorkbook.Worksheets("REPAIRS")
j = 4
For Each c In Source.Range("C4:C10000")
If c = "X" Then
Source.Rows(c.Row).Copy Target.Rows(j)
j = j + 1
End If
Next c
End Sub
I think this will achieve what you are looking for:
Sub CopyYes()
Dim myCell As Range
Dim LastColumnSource As Long 'Integer data type is outdated.
Dim LastRowTarget As Long
Dim SourceSheet As Worksheet
Dim TargetSheet As Worksheet
Dim SourceRange As Range
Dim TargetRange As Range
Dim myArray As Variant
Set SourceSheet = ActiveWorkbook.Worksheets("Sheet1") <~~ change to your sheet name
Set TargetSheet = ActiveWorkbook.Worksheets("Sheet2") <~~ change to your sheet name
'Change the 1 to whichever column you need (1 represents column A)
LastRowTarget = TargetSheet.Cells(Rows.Count, 1).End(xlUp).Row
LastRowSource = SourceSheet.Cells(Rows.Count, 3).End(xlUp).Row
Set SourceRange = SourceSheet.Range("C4:C" & LastRowSource)
j = 4
For Each myCell In SourceRange
If myCell.Value = "X" Then
LastColumnSource = SourceSheet.Cells(myCell.Row, Columns.Count).End(xlToLeft).Column
myArray = SourceSheet.Range(Cells(myCell.Row, 1), Cells(myCell.Row, LastColumnSource))
LastColumnTarget = TargetSheet.Cells(LastRowTarget, Columns.Count).End(xlToLeft).Column
Set TargetRange = TargetSheet.Range("A" & LastRowTarget)
TargetRange.Resize(1, UBound(myArray, 2)) = myArray
LastRowTarget = LastRowTarget + 1
End If
Next myCell
End Sub
To make it dynamic, the last row and last column are found for both sheets and the row is written to an array to then write back to the results sheet (which avoids the use of copy).
As I don't know enough about your project, I've left the ActiveWorkbook in but you'd be better to specify the workbook (or ThisWorkbook if it's the workbook the code is run from) - This avoids runtime errors if the code executes whilst another workbook is in focus.
Usually, I use an array to process, as follows
’--------------------------------
dim arr(),temp()
worksheets(1).activate
arr=[a1].currentregion
j=0
for i=1 to ubound(arr)
if arr(i)="x" then
j=j+1
redim preserve temp(j)
temp(j)=arr(i)
end if
next
worksheets(2).activate
range("a1:a"&ubound(temp))=temp
Try,
Sub CopyYes()
Dim Source As Worksheet
Dim Target As Worksheet
Dim vDB, vR()
Dim i As Long, n As Long, r As Long
Dim j As Integer, c As Integer
Set Source = ActiveWorkbook.Worksheets("MAINGANG")
Set Target = ActiveWorkbook.Worksheets("REPAIRS")
vDB = Source.UsedRange
r = UBound(vDB, 1)
c = UBound(vDB, 2)
For i = 4 To r
If vDB(i, 3) = "X" Then
n = n + 1
ReDim Preserve vR(1 To c, 1 To n)
For j = 1 To c
vR(j, n) = vDB(i, j)
Next j
End If
End If
Target.Range("a4").Resize(n, c) = WorksheetFunction.Transpose(vR)
End Sub

VBA. Deleting multiple cells in a row if one cell is blank

I have multiple columns in an excel sheet...say A1:D10.
I want to find any blank cells in column C, delete that cell as well as the A,B, and D cells of that same row, then shift up. But only in the range of A1:D10. I have other information in this excel sheet outside this range that I want to perserve in its original position. Therefore I can not use somthing like this:
.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Nor can I get something like the following to work, because it only shifts the single column up, not all four columns.
Set rng = Range("A1:D10").SpecialCells(xlCellTypeBlanks)
rng.Rows.Delete Shift:=xlShiftUp
If there is no data in columns A to D below row 10 that you don't want to move up, then SpecialCells and Delete Shift Up can be used like this
Sub Demo1()
Dim ws As Worksheet
Dim TestColumn As Long
Dim StartColumn As Long
Dim EndColumn As Long
Dim FirstRow As Long
Dim LastRow As Long
Dim i As Long
Dim rng As Range, arr As Range
' set up reference data
Set ws = ActiveSheet '<~~ update as required
TestColumn = 3 'C
StartColumn = 1 'A
EndColumn = 4 'D
FirstRow = 1
LastRow = 10
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With ws
On Error Resume Next
Set rng = .Range(.Cells(FirstRow, TestColumn), .Cells(LastRow, TestColumn)).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rng Is Nothing Then
For Each arr In rng.Areas
arr.EntireRow.Resize(, EndColumn - StartColumn + 1).Delete Shift:=xlShiftUp
Next
End If
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
If there is data in columns A to D below row 10 that you don't want to move up, then you can use Cut and Paste, like this
Sub Demo()
Dim ws As Worksheet
Dim TestColumn As Long
Dim StartColumn As Long
Dim EndColumn As Long
Dim FirstRow As Long
Dim LastRow As Long
Dim i As Long
' set up reference data
Set ws = ActiveSheet '<~~ update as required
TestColumn = 3 'C
StartColumn = 1 'A
EndColumn = 4 'D
FirstRow = 1
LastRow = 10
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With ws
If IsEmpty(.Cells(LastRow, TestColumn)) Then
.Cells(LastRow, StartColumn).Resize(1, EndColumn - StartColumn + 1).Clear
End If
For i = LastRow - 1 To FirstRow Step -1
If IsEmpty(.Cells(i, TestColumn)) Then
.Range(.Cells(i + 1, StartColumn), .Cells(LastRow, EndColumn)).Cut .Cells(i, StartColumn)
End If
Next
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Using Variant Array Method
Sub test2()
Dim rngDB As Range, vDB As Variant
Dim i As Integer, j As Integer, n As Integer
Dim k As Integer
Set rngDB = Range("a1:d10")
vDB = rngDB
n = UBound(vDB, 1)
For i = 1 To n
If IsEmpty(vDB(i, 3)) Then
For j = 1 To 4
If j <> 3 Then
vDB(i, j) = Empty
End If
Next j
End If
Next i
For j = 1 To 4
If j <> 3 Then
For i = 1 To n - 1
For k = i To n - 1
If vDB(k, j) = Empty Then
vDB(k, j) = vDB(k + 1, j)
vDB(k + 1, j) = Empty
End If
Next k
Next i
End If
Next j
rngDB = vDB
End Sub
The below will take care of your requirement by looking for an empty cell in column 3, and deleting the row and shifting up only in that row.
Sub deleteEmptyRow()
Dim i As Integer
For i = 1 To 10
If Cells(i, 3) = "" Then
Range(Cells(i, 1), Cells(i, 4)).delete Shift:=xlUp
End If
Next i
End Sub

Unable to arrange evenly scattered information from one sheet to another

I'm trying to arrange some uniformly scattered information from a spreadsheet to another. The information I'm interested in is in Sheet2 and I wish to place them in a customized manner in Sheet1.
I've tried with:
Sub ArrangeInformation()
Dim ws As Worksheet, cel As Range
Set ws = ThisWorkbook.Sheets("Sheet2")
Set tws = ThisWorkbook.Sheets("Sheet1")
For Each cel In ws.Range("A1:A" & ws.Cells(Rows.Count, 1).End(xlUp).row)
tws.Range(cel(1, 1).Address) = cel
Next cel
End Sub
The above script just replicates the same information in Sheet1 how they are in Sheet2.
Data in Sheet2:
How I like to arrange them in Sheet1:
How can I arrange those information in sheet1?
we can use some math to get the correct columns and rows:
Sub ArrangeInformation()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet2")
Dim tws As Worksheet
Set tws = ThisWorkbook.Sheets("Sheet1")
Dim i As Long
i = 0
Dim j As Long
j = 0
Dim cel As Range
For Each cel In ws.Range("A1:A" & ws.Cells(ws.Rows.Count, 1).End(xlUp).Row)
If cel <> "" Then
tws.Cells(Int(i / 4) + 1, ((j) Mod 4) + 1) = cel
i = i + 1
j = j + 1
End If
Next cel
End Sub
In the math the 4s are the number of items in each pattern
The INT will increase by 1 every four rounds and the MOD will repeat 1,2,3,4 every 4 rounds.
Just because:
this can be done with a formula:
=INDEX(Sheet2!$A:$A,INT(ROW(1:1)-1)/5+MOD((COLUMN(A:A)-1),5)+1)
where the 2 5s are the pattern and the +1 is the starting row of the data.
Put that in sheet1 A1 and copy over and down.
Maybe use Resize to transfer your data:
Sub Test()
Dim lr As Long, x As Long, y As Long
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
y = 1
lr = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
For x = 1 To lr Step 5
ws2.Cells(y, 1).Resize(, 4) = Application.Transpose(ws1.Cells(x, 1).Resize(4))
y = y + 1
Next x
End Sub
And propbably faster, you could assign your range to an array:
Sub Test()
Dim arr As Variant
Dim lr As Long, x As Long, y As Long
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
y = 1
lr = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
arr = ws1.Range("A1:A" & lr)
For x = LBound(arr) To UBound(arr) Step 5
ws2.Cells(y, 1).Resize(, 4) = Array(arr(x, 1), arr(x + 1, 1), arr(x + 2, 1), arr(x + 3, 1))
y = y + 1
Next x
End Sub
You'll need to manage which rows and columns you write to inside your loop. Something like:
Sub ArrangeInformation()
Dim ws As Worksheet, cel As Range
'New variables to manage rows and columns to write to
Dim writecol as integer, writeRow as integer
Set ws = ThisWorkbook.Sheets("Sheet2")
Set tws = ThisWorkbook.Sheets("Sheet1")
'Start in Row 1, Column 1
writeRow = 1
writeCol = 1
For Each cel In ws.Range("A1:A" & ws.Cells(Rows.Count, 1).End(xlUp).row)
tws.Range(writeRow, writeCol) = cel
'Next Column, or reset to 1 and iterate rows
If writeCol = 4 Then
writeCol = 1
writeRow = writeRow + 1
Else
writeCol = writeCol + 1
End If
Next cel
End Sub

Converting Headings in a single Column

I would like to convert all my heading of data in Column A
Before:
After:
Is there anyone could help? Thanks so much!
I think this might work for you
Option Explicit
Sub Stackoverflow()
Dim LR As Integer
Dim LC As Integer
Dim LRR As Integer
Dim i As Integer
Dim j As Integer
Dim wss As Object
Dim Sht As Object
Dim wsr As Object
Dim CreateSheetIF As Boolean
Set wss = ActiveWorkbook.ActiveSheet
'Create a sheet for the results
Set Sht = Nothing
On Error Resume Next
Set Sht = ActiveWorkbook.Worksheets("Results")
On Error GoTo 0
If Sht Is Nothing Then
CreateSheetIF = True
Worksheets.Add.Name = "Results"
Else
GoTo Exist
End If
Exist:
Set wsr = ActiveWorkbook.Sheets("Results")
LC = wss.Cells(1, Columns.Count).End(xlToLeft).Column
For i = 1 To LC
LR = wss.Cells(Rows.Count, i).End(xlUp).Row
For j = 1 To LR - 1
LRR = wsr.Cells(Rows.Count, 1).End(xlUp).Row
wsr.Range("A" & LRR + 1) = wss.Cells(1, i)
wsr.Range("B" & LRR + 1) = wss.Cells(j + 1, i)
Next
Next
End Sub
I haven't spend a lot of time doing this. So the code isn't pretty at all.
But it should work.
The Results will be paste on a new sheet called "Results".
Perhaps:
Sub ReOrganize()
Dim MaxCol As Long, Ic As Long, H As Variant
Dim s1 As Worksheet, s2 As Worksheet
Dim MaxRow As Long, K As Long, Jr As Long
Set s1 = Sheets("Sheet1")
Set s2 = Sheets("Sheet2")
MaxCol = s1.Cells(1, Columns.Count).End(xlToLeft).Column
For Ic = 1 To MaxCol
H = s1.Cells(1, Ic).Value
MaxRow = s1.Cells(Rows.Count, Ic).End(xlUp).Row
K = 2 * Ic - 1
For Jr = 2 To MaxRow
s2.Cells(Jr - 1, K) = H
s2.Cells(Jr - 1, K + 1) = s1.Cells(Jr, Ic).Value
Next Jr
Next Ic
End Sub

Resources