Looping and pasting based on cell value - loops

i have started this code, which looks in worksheet PCrun for "yes" in cell D2 then then copies A1:C9 and paste as an image to worksheet PCexport starting at cell A1.
This works but there are a few more steps i am stuck on.
I would like it to move on to the next range of cells A10:C18 looking in cell D11 for a yes.
This needs to continue i.e
D2 - C1:C9
D11 - A10:C28
D20 - A19:C27
and so on adding 9 each time and coping if there is a yes in D and pasting as an picture to the next avalible cell in worksheet PCexport.
Sub CopyIf()
Dim LastRow As Long, i As Long, erow As Long
Dim wsStr As String
Dim ws As Worksheet, wsC As Worksheet
Dim wb As Workbook, wbM As Workbook
Dim C As Range
LastRow = Worksheets("PCexport").Range("A" & Rows.Count).End(xlUp).Row
Set wb = ActiveWorkbook
Set wsC = wb.Sheets("PCrun")
erow = wsC.Cells(Rows.Count, 1).End(xlUp).Row
Worksheets("PCrun").Activate
For i = 1 To LastRow
If wsC.Cells(2, 4).Value = "YES" Then
erow = erow + 9
wsC.Range(wsC.Cells(1, 1), wsC.Cells(9, 3)).CopyPicture 'avoid select
Sheets("PCexport").Range("A1").PasteSpecial
End If
Next i End Sub

Some i came up with this.
`
Sub CopyIf()
Set Ask = Worksheets("PCrun").Range("$d2")
Set CP = Worksheets("PCrun").Range("a1:c9")
Set Give = Worksheets("PCexport").Range("$a1")
Worksheets("PCrun").Activate
For j = 0 To 135 Step 9
Set CPvar = CP.Offset(j, 0)
Set Askvar = Ask.Offset(j, 0)
Set Givevar = Give.Offset(j, 0)
If Askvar.Value = "YES" Then
CPvar.CopyPicture
With Sheets("PCexport").Range("A" & Rows.Count).End(xlUp).Offset(1).PasteSpecial
End With
End If
Next j
End Sub`

Try incorporating your for-step in your cell referencing
Sub CopyIf()
Dim LastRow As Long, i As Long, erow As Long
Dim ws As Worksheet, wsC As Worksheet
Dim wb As Workbook
Dim C As Range
LastRow = Worksheets("PCexport").Range("A" & Rows.Count).End(xlUp).Row
Set wb = ActiveWorkbook
Set wsC = wb.Sheets("PCrun")
erow = wsC.Range("A" & Rows.Count).End(xlUp).Row + 1
Worksheets("PCrun").Activate
For i = 0 To LastRow -1 Step 9
If wsC.Cells(2 + i, 4).Value = "YES" Then
wsC.Range(wsC.Cells(1 + i, 1), wsC.Cells(9 + i, 3)).CopyPicture 'avoid select 'not sure why you're opting for pictures
Sheets("PCexport").Range("A" & erow).PasteSpecial
erow = erow + 9 'you were filling your erow but weren't using it
End If
Next i
End Sub

This seems to do all i need.
{Sub CopyIf()
Dim i As Long, erow As Long
Dim wsStr As String
Dim ws As Worksheet, wsC As Worksheet
Dim wb As Workbook, wbM As Workbook
Dim C As Range}
Set Ask = Worksheets("PCrun").Range("$d2")
Set CP = Worksheets("PCrun").Range("a1:c9")
Set Give = Worksheets("PCexport").Range("$a1")
Set Take = Worksheets("PCexport").Range("a1")
Worksheets("PCrun").Activate
For j = 0 To 135 Step 9
Set CPvar = CP.Offset(j, 0)
Set Askvar = Ask.Offset(j, 0)
Set GiVevar = Give.Offset(j, 0)
Set Takevar = Take.Offset(j, 0)
If Askvar.Value = "YES" Then
CPvar.CopyPicture
GiVevar.Offset.PasteSpecial
Else
Takevar.Value = 1
End If
Next j
Worksheets("PCexport").Activate
Set Check = Worksheets("PCexport").Range("a1")
Set Take2 = Worksheets("PCexport").Range("A1:C9")
For k = 0 To 135 Step 9
Set Checkvar = Check.Offset(k, 0)
Set Take2var = Take2.Offset(k, 0)
If Checkvar.Value = "1" Then
Take2var.Delete
End If
Next k

Related

VBA array storing values from wrong worksheet due to redundantly defining worksheets

For whatever reason, when I print arr_in(1, 1) it gives me the value of arr_out(1, 1). Any clue as to why this might be happening?
Sub conceptos_import()
Dim wb As Workbook
Dim wb_in As Workbook
Dim wb_out As Workbook
Dim ws_in As Worksheet
Dim ws_out As Worksheet
Dim clls_in As Range
Dim clls_out As Range
Dim str As String
Dim str_in As String
Dim str_out As String
Dim path As String
Dim i As Long
Dim i_in As Long
Dim i_out As Long
Set wb = Application.Workbooks("rn_macros.xlsm")
path = wb.path & "\"
str = Application.GetOpenFilename()
Set wb_in = Application.Workbooks.Open(str)
Set ws_in = wb_in.Worksheets(1)
Set wb_out = Application.Workbooks.Open(path & "files\conceptos.xlsx")
Set ws_out = wb_out.Worksheets(1)
Set ws_in = wb_in.Worksheets(1)
Set ws_out = wb_out.Worksheets(1)
Dim arr_in() As Variant
With ws_in
Set clls_in = .Range(.Cells(1, 1), .Cells(lr(ws_in, 1), 1))
End With
arr_in = clls_in.Value2
Dim arr_out() As Variant
With ws_out
Set clls_out = .Range(.Cells(1, 1), .Cells(lr(ws_out, 1), 1))
End With
arr_out = clls_out.Value2
Debug.Print arr_in(1, 1)
For i_out = UBound(arr_out) To LBound(arr_out) + 1 Step -1
i = 0
str_out = arr_out(i_out, 1)
For i_in = UBound(arr_in) To LBound(arr_in) + 1 Step -1
str_in = arr_in(i_in, 1)
If str_out = str_in Then
i = 1
Exit For
End If
Next i_in
If i = 0 Then
ws_out.Cells(i_out, 1).EntireRow.Delete
End If
Next i_out
End Sub
All variables are properly defined in the sub (all wb_'s as workbooks, ws_'s as worksheets, clls_'s as ranges).
The lr function is a user defined function that uses the End.xlUp method to find last row, taking target worksheet and column as the input:
Public Function lr(ws As Worksheet, col As Long) As Long
lr = ws.Cells(ws.rows.Count, col).End(xlUp).row
End Function
Found the issue, and even though it is poorly written code, I don't understand why it was causing the arrays to misfire:
str = Application.GetOpenFilename()
Set wb_in = Application.Workbooks.Open(str)
Set ws_in = wb_in.Worksheets(1) 1st a
Set wb_out = Application.Workbooks.Open(path & "files\conceptos.xlsx")
Set ws_out = wb_out.Worksheets(1) 1st b
Set ws_in = wb_in.Worksheets(1) 2nd a
Set ws_out = wb_out.Worksheets(1) 2nd b
As you can see the lines Set ws_in =... and Set ws_out =... are repeated. By deleting the redundant lines I was able to get it to work. The final code would look like this:
Sub conceptos_import()
Dim wb As Workbook
Dim wb_in As Workbook
Dim wb_out As Workbook
Dim ws_in As Worksheet
Dim ws_out As Worksheet
Dim clls_in As Range
Dim clls_out As Range
Dim str As String
Dim str_in As String
Dim str_out As String
Dim path As String
Dim i As Long
Dim i_in As Long
Dim i_out As Long
Set wb = Application.Workbooks("rn_macros.xlsm")
path = wb.path & "\"
str = Application.GetOpenFilename()
Set wb_in = Application.Workbooks.Open(str)
Set ws_in = wb_in.Worksheets(1)
Set wb_out = Application.Workbooks.Open(path & "files\conceptos.xlsx")
Set ws_out = wb_out.Worksheets(1)
Dim arr_in() As Variant
With ws_in
Set clls_in = .Range(.Cells(1, 1), .Cells(lr(ws_in, 1), 1))
End With
arr_in = clls_in.Value2
Dim arr_out() As Variant
With ws_out
Set clls_out = .Range(.Cells(1, 1), .Cells(lr(ws_out, 1), 1))
End With
arr_out = clls_out.Value2
For i_out = UBound(arr_out) To LBound(arr_out) + 1 Step -1
i = 0
str_out = arr_out(i_out, 1)
For i_in = UBound(arr_in) To LBound(arr_in) + 1 Step -1
str_in = arr_in(i_in, 1)
If str_out = str_in Then
i = 1
Exit For
End If
Next i_in
If i = 0 Then
ws_out.Cells(i_out, 1).EntireRow.Delete
End If
Next i_out
End Sub

Convert subroutine to a function that can be used in a formula

I'm not very good with functions and was hoping someone could help convert this. I will be inserting the formula with a macro.
I have tried using formulas but run into issues when 2 or more matches are found.
The function will be inserted via macro like so.:
ws1.Range(Cells(x, spec), Cells(lRow, spec)).Formula = "=IFERROR(IF(OR(MID(RC[-3],SEARCH(""-"",RC[-3])+1,SEARCH(""-"",RC[-3],SEARCH(""-"",RC[-3])+1)-SEARCH(""-"",RC[-3])-1) = ""WP"",MID(RC[-3],SEARCH(""-"",RC[-3])+1,SEARCH(""-"",RC[-3],SEARCH(""-"",RC[-3])+1)-SEARCH(""-"",RC[-3])-1)=""DO""),""A15"",MID(RC[-3], FIND(CHAR(1),SUBSTITUTE(RC[-3],""-"",CHAR(1)," & aft & "))+1, FIND(CHAR(1),SUBSTITUTE(RC[-3],""-"",CHAR(1)," & aft + 1 & ")) - FIND(CHAR" & _
"(1),SUBSTITUTE(RC[-3],""-"",CHAR(1)," & aft & "))-1)),"""")" & ""
Sub Test()
Dim ws1, ws2 As Worksheet
Dim SrchRng As Range, cel As Range
Dim SrchStr As String
Dim myList, tbl As Object
Dim arr As Variant
Dim i, x As Integer
Dim val as String
Set ws1 = ThisWorkbook.Sheets("Index")
Set ws2 = ThisWorkbook.Sheets("Data Entry")
Set SrchRng = ws1.Range("A2:A30")
Set myList = CreateObject("System.Collections.ArrayList")
SrchStr = ws2.Range("AB7")
For Each cel In SrchRng
If InStr(1, SrchStr, cel.Value, vbTextCompare) > 0 Then
myList.Add cel.Value
arr = myList.Toarray
End If
Next cel
'######### Need to compare string length and keep the highest value ##########
For i = LBound(arr) To UBound(arr)
If IsNull(x) Or Len(arr(i)) > x Then
x = Len(arr(i))
val = arr(i)
End If
Next i
ws2.Range("AE7") = val
Debug.Print x
Debug.Print a
Set ws1 = Nothing
Set ws2 = Nothing
Set SrchRng = Nothing
Set myList = Nothing
End Sub
EDITED due to updated question.
A double loop will conduct a one to one search against the data to ensure that any duplicate entries are caught and correctly labelled.
Assuming there is some consistency with the formatting, this will look for the search criteria and - (ie: "A12UG-"). This will eliminate "A12UG" from triggering with "A12".
To call the function, assign the call to a variable. ie: varName = updateAE()
Function updateAE()
Dim ws1: Set ws1 = ThisWorkbook.Sheets("Index")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Data Entry")
Dim srchRng As Range, indexRng As Range, indexCel As Range, srchCel As Range
Dim i As Integer
Dim count As Integer
Dim indexLRow, srchLRow As Long
indexLRow = ws1.Cells(ws2.Rows.count, "A").End(xlUp).Row
srchLRow = ws2.Cells(ws2.Rows.count, "AB").End(xlUp).Row
Set indexRng = ws1.Range("A1:A" & indexLRow)
Set srchRng = ws2.Range("AB3:AB" & srchLRow)
count = 1
On Error Resume Next
For Each indexCel In indexRng
For Each srchCel In srchRng
If InStr(1, srchCel, indexCel & "-") > 0 And Len(indexCel) > 0 Then
ws2.Range("AE" & count + 2) = indexCel
End If
count = count + 1
Next srchCel
count = 1
Next indexCel
End Function
Output:

Storing cell addresses into an array in vba while using a loop

I am trying to work through a code that utilizes a system to check two different worksheets by using a for loop and highlight the differences/edits made in the second sheet ("Version 2") onto the first sheet ("Original"). I have a feeling that I need to utilize an array but I'm not advanced enough where I know how to store the values and then later write them onto another sheet (down below).
I've gotten the code so that it highlights all the relevant cells, but now I'm trying to output it into a report (on another sheet called 'Logged Changes') which will summarize all the cell addresses where edits were made. Please forgive all the variables as this is from an old code set where variables are not explicitly defined:
Private Sub CompareBasic()
Dim actSheet As Range
Dim k As Integer
Dim o As Long
Dim p As Long
Dim i As Integer
Dim change As Integer
o = Worksheets("Original").Cells(2, Columns.Count).End(xlToLeft).Column
p = Worksheets("Original").Range("A" & Rows.Count).End(xlUp).Row
change = 0
Sheets("Original").Select
For i = 2 To p
For k = 1 To o
If IsNumeric(Worksheets("Original").Cells(i, k).Value) = True Then
If Worksheets("Original").Cells(i, k).Value <> Worksheets("Version 2").Cells(i, k).Value Then
Worksheets("Original").Cells(i, k).Interior.ColorIndex = 37
change = change + 1
End If
Else
If StrComp(Worksheets("Original").Cells(i, k), Worksheets("Version 2").Cells(i, k), vbBinaryCompare) <> 0 Then
Worksheets("Original").Cells(i, k).Interior.ColorIndex = 37
change = change + 1
End If
End If
Next k
Next i
Unload Me
MsgBox "Number of cells edited counted: " & change, vbOKOnly + vbExclamation, "Summary"
b = Empty
answer = MsgBox("Do you want to run the Report?", vbYesNo + vbQuestion)
If answer = vbYes Then
If Sheet_Exists("Logged Changes") = False Then
Sheet_Name = "Logged Changes"
Worksheets.Add(After:=Sheets(Sheets.Count)).Name = Sheet_Name
End If
Worksheets("Logged Changes").Range("A1") = "Edited Requirements"
Else
Unload Me
End If
End Sub
I have tried fiddling around with the code, but didn't want to clog it up with any unnecessary/broken lines. Any help would be greatly appreciated!
Try this:
Option Explicit
Private Sub CompareBasic()
Const SHT_REPORT As String = "Logged Changes"
Dim actSheet As Range
Dim c As Integer
Dim o As Long
Dim p As Long
Dim r As Long
Dim change As Long, wsOrig As Worksheet, wsNew As Worksheet, wsReport As Worksheet
Dim dataOrig, dataNew, rngData As Range, v1, v2, bDiff As Boolean
Dim arrUpdates
Set wsOrig = Worksheets("Original")
Set wsNew = Worksheets("Version 2")
o = wsOrig.Cells(2, Columns.Count).End(xlToLeft).Column
p = wsOrig.Range("A" & Rows.Count).End(xlUp).Row
Set rngData = wsOrig.Range("A2", wsOrig.Cells(p, o))
dataOrig = rngData.Value 'get an array of data
dataNew = wsNew.Range(rngData.Address).Value 'array of new data
ReDim arrUpdates(1 To rngData.Cells.Count, 1 To 3) 'for change info
change = 0
For r = 1 To UBound(dataOrig, 1)
For c = 1 To UBound(dataOrig, 2)
v1 = dataOrig(r, c)
v2 = dataNew(r, c)
If Len(v1) > 0 Or Len(v2) > 0 Then
If IsNumeric(v1) Then
bDiff = v1 <> v2
Else
bDiff = StrComp(v1, v2, vbBinaryCompare) <> 0
End If
End If
'any difference?
If bDiff Then
change = change + 1
With rngData.Cells(r, c)
arrUpdates(change, 1) = .Address
.Interior.ColorIndex = 37
End With
arrUpdates(change, 2) = v1
arrUpdates(change, 3) = v2
End If
Next c
Next r
If MsgBox("Do you want to run the Report?", vbYesNo + vbQuestion) = vbYes Then
With GetSheet(SHT_REPORT, ThisWorkbook)
.UsedRange.ClearContents
.Range("A1") = "Edited Requirements"
.Range("A3").Resize(1, 3).Value = Array("Address", wsOrig.Name, wsNew.Name)
.Range("A4").Resize(change, 3).Value = arrUpdates
End With
Else
'Unload Me
End If
End Sub
'return as sheet from wb by name (and create it if it doesn't exist)
Function GetSheet(wsName, wb As Workbook) As Worksheet
Dim rv As Worksheet
On Error Resume Next
Set rv = wb.Worksheets(wsName)
On Error GoTo 0
If rv Is Nothing Then
Set rv = wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.Count))
rv.Name = "Logged Changes"
End If
Set GetSheet = rv
End Function
Sheet Differences
Option Explicit
Sub logChanges()
Const ws1Name As String = "Original"
Const ws2Name As String = "Version 2"
Const wsResult As String = "Logged Changes"
Const FirstRow As Long = 2
Const FirstColumn As Long = 1
Const LastRowColumn As Long = 1
Const LastColumnRow As Long = 2
Const ResultFirstCell As String = "A2"
Dim Headers As Variant
Headers = Array("Id", "Address", "Original", "Version 2")
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(ws1Name)
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, LastRowColumn).End(xlUp).Row
Dim LastColumn As Long
LastColumn = ws.Cells(LastColumnRow, ws.Columns.Count) _
.End(xlToLeft).Column
Dim rng As Range
Set rng = ws.Range(ws.Cells(FirstRow, FirstColumn), _
ws.Cells(LastRow, LastColumn))
Dim Data1 As Variant: Data1 = rng.Value
Set ws = wb.Worksheets(ws2Name)
Dim Data2 As Variant: Data2 = ws.Range(rng.Address).Value
Dim Result() As Variant
Dim i As Long, j As Long, k As Long
For i = 1 To UBound(Data1)
For j = 1 To UBound(Data1, 2)
If Data1(i, j) <> Data2(i, j) Then GoSub writeResult
Next j
Next i
If k > 0 Then
transpose2D Result
On Error GoTo MissingResultSheet
Set ws = wb.Worksheets(wsResult)
On Error GoTo 0
ws.Range(ws.Range(ResultFirstCell), _
ws.Cells(ws.Rows.Count, ws.Columns.Count)).Clear
ws.Range(ResultFirstCell).Resize(k, UBound(Result, 2)).Value = Result
MsgBox "Found '" & k & "' difference(s) in range '" _
& rng.Address(False, False) & "'.", vbInformation
Else
MsgBox "Found no differences in range '" _
& rng.Address(False, False) & "'.", vbExclamation
End If
Exit Sub
writeResult:
k = k + 1
ReDim Preserve Result(1 To 4, 1 To k)
Result(1, k) = k
Result(2, k) = getAddress(i + FirstRow - 1, j + FirstColumn - 1)
Result(3, k) = Data1(i, j)
Result(4, k) = Data2(i, j)
Return
MissingResultSheet:
If Err.Number = 9 Then
wb.Worksheets.Add After:=wb.Sheets(wb.Sheets.Count)
With ActiveSheet
.Name = wsResult
If .Range(ResultFirstCell).Row > 1 Then
.Range(ResultFirstCell).Offset(-1) _
.Resize(, UBound(Headers) + 1).Value = Headers
End If
End With
Resume ' i.e. the code continues with Set ws = wb.Worksheets(wsResult)
Else
'?
Exit Sub
End If
End Sub
Function getAddress(aRow As Long, aColumn As Long) As String
getAddress = ActiveSheet.Cells(aRow, aColumn).Address(False, False)
End Function
Sub transpose2D(ByRef Data As Variant)
Dim i As Long, j As Long
Dim Result As Variant
ReDim Result(LBound(Data, 2) To UBound(Data, 2), _
LBound(Data) To UBound(Data))
For i = LBound(Data) To UBound(Data)
For j = LBound(Data, 2) To UBound(Data, 2)
Result(j, i) = Data(i, j)
Next j
Next i
Data = Result
End Sub
This solution for converting a column number to a string without using objects Function to convert column number to letter? could be used to write a descent getAddress function.

Need a VBA code to convert Excel sheet columns into tab in new Excel sheet

I have an Excel sheet having 3000 columns and I need to convert this sheet in such a way that one tab will contain 254 columns only and remaining will go to the next tab. So I need a VBA code (Macro) which can perform the same.
As of now I wrote the following code only which is creating 3000 tabs with one column in each, also it is going to infinite loop as I did not put any condition there for blank column.
Sub SpliteIntoMultipleTab()
'
' createtemplates Macro
Dim WS As Worksheet
Dim SS As Worksheet
Dim TemplateName As String
Dim tempstr As String
'
Dim CurCol As String
Dim Template As String
Dim xColIndex As Integer
Dim xRowIndex As Integer
Dim WSCount As Integer
'==========================================================================
'Declarations
CurCol = 1
Template = "Sheet1"
'==========================================================================
Set SS = Worksheets(Template)
If WS Is Nothing Then
Start:
With ActiveWorkbook
Set WS = .Sheets.Add(After:=ActiveSheet)
WSCount = Sheets.Add(After:=Sheets(Worksheets.Count))
On Error Resume Next
Set WS = Worksheets("temp")
WS.Name = SS.Range("A1").Value
End With
Else
End If
SS.Activate
xIndex = Application.ActiveCell.Column
xRowIndex = Application.ActiveSheet.Cells(Rows.Count, xIndex).End(xlUp).Row
Range(Cells(1, xIndex), Cells(xRowIndex, xIndex)).Select
Selection.Copy
WS.Select
WS.Range("A1").Select
ActiveSheet.Paste
SS.Columns(1).EntireColumn.Delete
CurCol = CurCol + 1
GoTo Start
End Sub
Use integer division and modulus, so for example taking the 1000th column
1000 \ 254 = 3
1000 mod 254 = 238
gives the 3rd sheet and the 238th column.
So loop through from 1 to 3000 using \ and mod.
You code is very non-standard and I cannot get my head around it, I suggest you start from my code, this is an illustrative example of breaking a block of data into separate sheets. Copy the code into a new workbook then
Run CreateSheetAndPopulateWithBlockOfData once only to create a block of data.
Run Test to run the BreakBlockIntoChunks routine, you can experiment with the chunk size.
Option Explicit
Private Const csSHEETNAME As String = "Source"
Sub TestCreateSheetAndPopualteWithBlockOfData()
Dim wsSource As Excel.Worksheet
Set wsSource = CreateSheetAndPopulateWithBlockOfData(ThisWorkbook, csSHEETNAME, 20, 100)
End Sub
Sub Test()
Dim wsSource As Excel.Worksheet
Set wsSource = ThisWorkbook.Worksheets.Item(csSHEETNAME)
'Stop
Dim wbResults As Excel.Workbook
Set wbResults = Workbooks.Add
BreakBlockIntoChunks wsSource, 5, wbResults
End Sub
Function BreakBlockIntoChunks(ByVal wsSource As Excel.Worksheet, ByVal lColumnChunkSize As Long, ByVal wbDestinationWorkbook As Excel.Workbook)
Dim rngDataBlock As Excel.Range
Set rngDataBlock = wsSource.Cells(1, 1).CurrentRegion
Dim lSourceColumnCount As Long
lSourceColumnCount = rngDataBlock.Columns.Count
Dim lSourceRowCount As Long
lSourceRowCount = rngDataBlock.Rows.Count
Dim lColumnLoop As Long
For lColumnLoop = 1 To lSourceColumnCount
Dim lCurrentSheet As Long
lCurrentSheet = ((lColumnLoop - 1) \ lColumnChunkSize) + 1
Dim wsCurrentSheet As Excel.Worksheet
If lCurrentSheet > wbDestinationWorkbook.Worksheets.Count Then Set wsCurrentSheet = wbDestinationWorkbook.Worksheets.Add
If wsCurrentSheet Is Nothing Then Set wsCurrentSheet = wbDestinationWorkbook.Worksheets.Item(lCurrentSheet) '* runs first loop
'**ADD your sheet naming logic here perhaps
Dim lCurrentColumn As Long
lCurrentColumn = ((lColumnLoop - 1) Mod lColumnChunkSize) + 1
Dim rngSource As Excel.Range
Set rngSource = wsSource.Range(wsSource.Cells(1, lColumnLoop), wsSource.Cells(lSourceRowCount, lColumnLoop))
Dim rngDestination As Excel.Range
Set rngDestination = wsCurrentSheet.Range(wsCurrentSheet.Cells(1, lCurrentColumn), wsCurrentSheet.Cells(lSourceRowCount, lCurrentColumn))
rngDestination.Value2 = rngSource.Value2 '* <---Copies without using clipboard
Next lColumnLoop
End Function
Function CreateSheetAndPopulateWithBlockOfData(ByVal wb As Excel.Workbook, ByVal sSheetName As String, ByVal lRowsDeep As Long, ByVal lColumnsWide As Long) As Excel.Worksheet
Dim ws As Excel.Worksheet
Set ws = wb.Worksheets.Add
ws.Name = sSheetName
Dim rngBlock As Excel.Range
Set rngBlock = ws.Range(ws.Cells(1, 1), ws.Cells(lRowsDeep, lColumnsWide))
rngBlock.Formula = "=RANDBETWEEN(1,100000)"
rngBlock.Value2 = rngBlock.Value2
Set CreateSheetAndPopulateWithBlockOfData = ws
End Function
you could try this:
Sub SpliteIntoMultipleTab()
Dim colNum As Long, iCol As Long
With Worksheets("Sheet1").UsedRange
colNum = .Columns.count
Do
Worksheets.Add(After:=Worksheets(Worksheets.count)).Range("A1:IT1").Resize(.Rows.count).Value = .Columns(iCol + 1).Resize(, 254).Value
iCol = iCol + 254
colNum = colNum - 254
Loop While colNum > 0
End With
End Sub
which copies values only and speed up things considerably

Error in converting Range to arrays

Anybody please help me figure my problem out?
Dim attPresent as Variant ' attpresent()
Set ws = thisworkbook.sheets("Sheet1")
lastrow = ws.cells(Rows.count, 8).end(xlup).row
attPresent = ws.Range("H4:H" & lastrow).Value 'errors if I use Dim attPresent() As Variant
For k = LBound(attPresent, 1) To UBound(attPresent, 1) ' Dim attPresent As Variant'errors if I use
msgbox attpresent(k,1)
Next
This line attPresent = ws.Range("H4:H" & lastrow).Value returns an error if I declare the variable as Dim attPresent() As Variant. Whereas, if declare the variable as Dim attPresent As Variant, this line For k = LBound(attPresent, 1) To UBound(attPresent, 1) errors.
Can anyone please help me clear this out?Thanks
As a good practice, try to remember to use Option Explicit, and also declare all your variables.
When you use Dim attPresent() As Variant to declare you array , and later on you insert values from a Range to your Array with attPresent = .Range("H4:H" & lastrow).Value, it will automatically Redim your array to 2-dimensinal array (1 to Row number, 1 to Column Number).
Option Explicit
Sub RngtoArray()
Dim attPresent() As Variant
Dim ws As Worksheet
Dim lastrow As Long
Dim k As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
lastrow = .Cells(.Rows.Count, 8).End(xlUp).Row
attPresent = .Range("H4:H" & lastrow).Value
End With
For k = 1 To UBound(attPresent, 1)
MsgBox attPresent(k, 1)
Next
End Sub
Edit 1: A slightly different approach, in case there is only 1 cell in the Range:
With ws
lastrow = .Cells(.Rows.Count, 8).End(xlUp).Row
' for single column only - create a 1-Dimension array
ReDim attPresent(1 To lastrow - 4 + 1) ' when the Range starts from "H4"
For k = 1 To UBound(attPresent)
attPresent(k) = .Cells(4 + k - 1, "H")
Next k
End With
For k = 1 To UBound(attPresent)
MsgBox attPresent(k)
Next
I tried to separate the stuff that you had already defined but for clarity I thought I'd provide my full code:
Sub test()
Dim lastrow, i As Integer
Dim ws As Worksheet
Set ws = ActiveWorkbook.Worksheets("Sheet1")
Dim attPresent() As Variant
lastrow = ws.Cells(Rows.Count, "H").End(xlUp).Row
ReDim attPresent(lastrow - 4)
For i = 4 To lastrow
attPresent(i - 4) = ws.Range("H" & i).Value
Next
msg = Join(attPresent, " ")
MsgBox "The array holds: " & vbNewLine & msg
End Sub
I defined the array without a size to begin with then redefined it to the size it needs to be at a later stage once you know the lastrow (as you started on 4 i deducted 4 from lastrow).
I guessed the msgBox was to test what you had gathered so I created a dump that prints them all into one box but obviously change that if you have a lot of data. xD
To work with arrays I always loop through each individual entry, storing them one at a time. I'm not even sure whether you can dump an entire range into one in one step as I've never even looked into it. Anyway, I hope this solves your problem kupo.
Function RangeToArray(rng As Range)
Dim myArray() As Variant, ws As Worksheet
fr = rng.Row
fc = rng.Column
r = rng.Rows.Count
c = rng.Columns.Count
Set ws = rng.Worksheet
ReDim myArray(r - 1, c - 1)
For i = 0 To r - 1
For j = 0 To c - 1
myArray(i, j) = ws.Cells(fr + i, fc + j).Value2
Next j
Next i
RangeToArray = myArray
End Function
Sub f()
Dim rng As Range, attPresent() As Variant ' attpresent()
Set ws = ThisWorkbook.ActiveSheet 'Sheets("Sheet1")
lastrow = ws.Cells(Rows.Count, 8).End(xlUp).Row
Set rng = ws.Range("H4:H" & lastrow)
attPresent = RangeToArray(rng)
For k = LBound(attPresent, 1) To UBound(attPresent, 1) ' Dim attPresent As Variant'errors if I use
MsgBox attPresent(k, 0)
Next
End Sub
I created a more generic function that you can call in this specific case as well.

Resources