I have a list of values in cells A1:A75, and a button to randomly select one and display it in cell D3:
Sub BingoGen()
Dim ws As Worksheet
Dim stRow As Long, endRow As Long, dataCol As Long
Dim dispRow As Long, dispCol As Long
Set ws = Sheets("BingoHome")
stRow = 2
dataCol = 1
dispRow = 3
dispCol = 4
With ws
endRow = .Cells(.Rows.Count, dataCol).End(xlUp).Row
.Cells(dispRow, dispCol).Value = _
.Cells(Application.RandBetween(stRow, endRow), dataCol).Value
End With
I would like to alter this to begin by showing the value in A1 and work down the list with each button click.
I have another macro button that will randomize this list of values.
I would use a static variable to store the location the presently referenced cell.
Sub BingoGen()
Dim ws As Worksheet
Dim stRow As Long, endRow As Long, dataCol As Long
Dim dispRow As Long, dispCol As Long
Static dataRow As Integer
Set ws = Sheets("BingoHome")
stRow = 2
dataCol = 1
dispRow = 3
dispCol = 4
With ws
'if you will always have 75 rows I would just use endRow = 75
endRow = .Cells(.Rows.Count, dataCol).End(xlUp).Row
'if the data row is undefined or larger than the end row
If dataRow < 1 Or dataRow > endRow Then
dataRow = 1
'otherwise (1<= dataRow <= endRow) index dataRow by 1
Else
dataRow = dataRow + 1
End If
.Cells(dispRow, dispCol).Value = .Cells(dataRow, dataCol).Value
End With
Also, out of curiosity is there a reason that you are typing all of your variables as Long, when they would easily fit in an Integer?
Related
I'm seeking assistance with copying and pasting specific cells that meet a requirement from my source data sheet to a "dashboard" sheet. I have the code below but when I run the macro it only copy and pastes the last row that meets the criteria, not all rows that meet the criteria.
For reference, I am copying 3 cells from a row in a table on the source data sheet, that may increase or decrease in size any given day, and pasting the 3 cells to the bottom of a different table in the dashboard sheet.
Any help is appreciated, thanks!
Sub CopyPaste()
Dim SourceData As Worksheet
Dim Dashboard As Worksheet
Dim searchString As String
Dim lastSourceRow As Long
Dim startSourceRow As Long
Dim lastTargetRow As Long
Dim sourceRowCounter As Long
Dim columnToEval As Long
Dim columnCounter As Long
Dim columnsToCopy As Variant
Dim columnsDestination As Variant
Set SourceData = ThisWorkbook.Worksheets("Source Data")
Set Dashboard = ThisWorkbook.Worksheets("Dashboard")
columnsToCopy = Array(7, 8, 11)
columnsDestination = Array(2, 3, 4)
searchString = "New"
startSourceRow = 3
columnToEval = 45
lastSourceRow = SourceData.Cells(SourceData.Rows.Count, 1).End(xlUp).Row
For sourceRowCounter = startSourceRow To lastSourceRow
If SourceData.Cells(sourceRowCounter, columnToEval).Value = searchString Then
lastTargetRow = Dashboard.Cells(Dashboard.Rows.Count, 1).End(xlUp).Row
For columnCounter = 0 To UBound(columnsToCopy)
Dashboard.Cells(lastTargetRow, columnsDestination(columnCounter)).Offset(1, 0).Value = SourceData.Cells(sourceRowCounter, columnsToCopy(columnCounter)).Value
Next columnCounter
End If
Next sourceRowCounter
SourceData.Activate
End Sub
Following from comments above:
Sub CopyPaste()
Dim SourceData As Worksheet
Dim Dashboard As Worksheet
Dim searchString As String
Dim lastSourceRow As Long
Dim startSourceRow As Long
Dim lastTargetRow As Long
Dim sourceRowCounter As Long
Dim columnToEval As Long
Dim columnCounter As Long
Dim columnsToCopy As Variant
Dim columnsDestination As Variant
Set SourceData = ThisWorkbook.Worksheets("Source Data")
Set Dashboard = ThisWorkbook.Worksheets("Dashboard")
columnsToCopy = Array(7, 8, 11)
columnsDestination = Array(2, 3, 4)
searchString = "New"
startSourceRow = 3
columnToEval = 45
lastTargetRow = Dashboard.Cells(Dashboard.Rows.Count, 1).End(xlUp).Row 'move this out of the loop
lastSourceRow = SourceData.Cells(SourceData.Rows.Count, 1).End(xlUp).Row
For sourceRowCounter = startSourceRow To lastSourceRow
If SourceData.Cells(sourceRowCounter, columnToEval).Value = searchString Then
For columnCounter = 0 To UBound(columnsToCopy)
Dashboard.Cells(lastTargetRow, columnsDestination(columnCounter)).Offset(1, 0).Value = _
SourceData.Cells(sourceRowCounter, columnsToCopy(columnCounter)).Value
Next columnCounter
lastTargetRow = lastTargetRow + 1 'next destination row
End If
Next sourceRowCounter
SourceData.Activate
End Sub
What I want to achieve is to use values via a loop in another module.
My Excel file has 3 columns with each column 2 rows.
I want to use the values in each row (3 columns) inside an other method.
My loop script
Sub Loops()
Dim lRow As Long
Dim lCol As Long
Dim ws As Worksheet
Dim rng As Range, cell As Range
Set rng = Range("E1")
Set ws = Sheet1
Row = 1
lRow = Cells(Rows.Count, 1).End(xlUp).Row
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
For Each cell In rng
For icol = 1 To lCol
For irow = 1 To lRow
cell(Row).Value = ws.Cells(irow, icol)
Row = Row + 1
Next irow
Next icol
Next cell
End Sub
Main Script
Sub Main()
Dim text1 As String
Dim text2 As String
Dim text3 As String
text1 = ThisWorkbook.Sheets(1).Range("A1")
text2 = ThisWorkbook.Sheets(1).Range("B1")
text3 = ThisWorkbook.Sheets(1).Range("C1")
Debug.Print text1; text2; text3
End Sub
As you can see in the Main script I have put in a hard link to the info that I need.
So I want to first get the values of row 1 (Columns A, B & C) and do something.
When this is done I want to get the values of row 2 (Columns A, B & C) and do something.
I want this to go through untill there are no more rows.
Can anyone point me in the right direction on how to achieve this? Thank you.
UPDATE
This is my excel file
So the Main Script should give as result
text1 = 1
text2 = 3
text3 = 5
When this is done the Main Script should run again. With result.
text1 = 2
text2 = 4
text3 = 6
And as there is no more row the script needs to stop.
If you want to do the same thing for every cell do something like this
Public Sub LoopingLouiCellWise()
Dim ws As Worksheet
Set ws = Sheet1
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim LastCol As Long
LastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
Dim iRow As Long
For iRow = 1 To LastRow 'loop through all rows
Dim iCol As Long
For iCol = 1 To LastCol 'loop through columns in this row
'either put your entire code to do something here
'…
'or call a sub procedure
DoSomethingWithCell ws.Cells(iRow, iCol)
Next iCol
Next iRow
End Sub
Private Sub DoSomethingWithCell(ByVal Cell As Range)
'your code here
Debug.Print Cell.Address
End Sub
If you want to do "something" with the entire row (row wise) then do something like this
Public Sub LoopingLouiRowWise()
Dim ws As Worksheet
Set ws = Sheet1
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim LastCol As Long
LastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
Dim iRow As Long
For iRow = 1 To LastRow 'loop through all rows
DoSomethingWithRow iRow, LastCol, ws
Next iRow
End Sub
Private Sub DoSomethingWithRow(ByVal iRow As Long, ByVal LastCol As Long, ByVal ws As Worksheet)
'your code here
Dim iCol As Long
For iCol = 1 To LastCol
Debug.Print ws.Cells(iRow, iCol)
Next iCol
End Sub
Note that in this version you need to tell your procedure in which worksheet ws you are working.
I have a VBA script in an excel workbook that loops through a large number of sheets (around 100) to merge data onto a single sheet. This is also data exported from PDF files. I tried to clean all non-printable characters and formatting but I'm not sure if I missed some.
It uses a single For Each ws In Workbook loop but when executed the script loops through the workbook a seemingly random number of times and stops at a seemingly random worksheet. This causes a problem because sometimes when executed, the summary become 10K lines instead of 1K.
Does anyone have any idea why this is happening?
Since the data is imported from a PDF, it is not formatted in a useful way. I have other scripts that get me to this point where I can merge and use power query. Layout of each worksheet is:
|------|---------------|---------|--------------|----------|
| Buy | Description | Symbol | Price ($) | null |
| null | Lrg Co | VOO | $242.55 | 1/2/2018 |
| cont....
And the VBA Code (Not the prettiest but gets the job done... almost ):
Sub summarize()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim i As Integer
Dim stcol As Integer
Dim endcol As Integer
Dim strow As Integer
Dim endrow As Integer
Dim symrng As Range
Dim totrow As Integer
Dim j As Integer
Dim itm As Range
Dim lr As Long
j = 1
For Each ws In Worksheets
stcol = 1
Set symrng = ws.Cells.Find("Symbol", LookAt:=xlPart, MatchCase:=False)
strow = symrng.Row
endcol = symrng.Offset(1, 0).End(xlToRight).Column
endrow = ws.Cells.SpecialCells(xlCellTypeLastCell).Row
Set symrng = Nothing
totrow = endrow - strow
For i = 0 To totrow
Worksheets("Summary").Range(Worksheets("Summary").Cells(j + 1, 1), Worksheets("Summary").Cells(j + 1, endcol)).Value = itm.Value
j = j + 1
Next i
Next ws
Application.ScreenUpdating = True
End Sub
Thank you #FoxFireBurnsandBurns for the idea, I ran the script with only a few sheets. I wasn't testing for the Summary so it kept iterating through the imported data until I'm guessing excel triggered a memory circuit breaker. Adding this line fixed it:
If ws.Name = "Summmary" Then GoTo Nextws:
The complete code is:
Sub summarize()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim i As Integer
Dim stcol As Integer
Dim endcol As Integer
Dim strow As Integer
Dim endrow As Integer
Dim symrng As Range
Dim totrow As Integer
Dim j As Integer
Dim itm As Range
Dim lr As Long
j = 1
For Each ws In Worksheets
' Exclude Summary Sheet
If ws.Name = "Summmary" Then GoTo Nextws:
stcol = 1
Set symrng = ws.Cells.Find("Symbol", LookAt:=xlPart, MatchCase:=False)
strow = symrng.Row
endcol = symrng.Offset(1, 0).End(xlToRight).Column
endrow = ws.Cells.SpecialCells(xlCellTypeLastCell).Row
Set symrng = Nothing
totrow = endrow - strow
For i = 0 To totrow
Worksheets("Summary").Range(Worksheets("Summary").Cells(j + 1, 1), Worksheets("Summary").Cells(j + 1, endcol)).Value = itm.Value
j = j + 1
Next i
Nextws:
Next ws
Application.ScreenUpdating = True
End Sub
I am trying to get my macro(next word) to select a random word from a list and then another macro(definition) does a vlookup to return the definition. When I select the macro to grab a new word I need it to clear the macro for the definition so that I cant see it until i select the definition button. Right now i get runtime error 1004 and it highlights my .clearcontent code at the end.
Sub showRandomWord()
Dim ws As Worksheet, ws2 As Worksheet
Dim stRow As Long, endRow As Long, dataCol As Long
Dim dispRow As Long, dispCol As Long
Set ws = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
stRow = 2
dataCol = 1
dispRow = 2
dispCol = 2
With ws
endRow = .Cells(.Rows.Count, dataCol).End(xlUp).Row
End With
ws2.Cells(dispRow, dispCol).Value =
ws.Cells(Application.RandBetween(stRow, endRow), dataCol).Value
Worksheets("Sheet2").Range("J2").ClearContents
End Sub
Use MergeArea?
Sub showRandomWord()
Dim ws As Worksheet, ws2 As Worksheet
Dim stRow As Long, endRow As Long, dataCol As Long
Dim dispRow As Long, dispCol As Long
Set ws = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
stRow = 2
dataCol = 1
dispRow = 2
dispCol = 2
With ws
endRow = .Cells(.Rows.Count, dataCol).End(xlUp).Row
End With
ws2.Cells(dispRow, dispCol).Value = ""
ws.Cells(Application.RandBetween(stRow, endRow), dataCol).Value
ws2.Range("J2").MergeArea.ClearContents
End Sub
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