Is there a way to define and use a single cell? - excel

I'm trying to single out a single cell, not a constant as it depends on the data at hand.
Dim lastrow As Integer
Dim sumcount As Integer
'find last non-empty row in column C
lastrow = Cells(Rows.Count, 3).End(xlUp).Row
'add up the int values in the range in C
sumcount = Application.WorksheetFunction.Sum(Range("C17", Cells(lastrow, 3)))
'result goes into the next empty cell in C
Cells(lastrow + 1, 3).Value = sumcount
Now I'm trying to throw the cell Cells(lastrow + 1, 3) into a variable so I can offset it and assign that offset cell a string value.
As far as I know that's only possible with the Range object, but I can't figure out the syntax to achieve that. Is there a property or method I'm not aware of?

Add Column Total and Write to Cell Adjacent To the Right
Option Explicit
Sub Test()
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim sfCell As Range: Set sfCell = ws.Range("C17")
Dim slCell As Range: Set slCell = ws.Cells(ws.Rows.Count, "C").End(xlUp)
Dim srg As Range: Set srg = ws.Range(sfCell, slCell)
Dim sSum As Double: sSum = Application.Sum(srg)
Dim dCell As Range: Set dCell = slCell.Offset(1)
dCell.Value = sSum
dCell.Offset(, 1) = "some string" ' adjacent to the right
End Sub

Cells returns a range object. So you should be able to simply do:
set myrange = cells(lastrow + 1, 3)
myrange.value = "string"

Related

Error 400 when trying to operate with all used cells in Excel with VBA

I'm trying to take the first column from my file (all rows except header) and delete text to the left of a colon character but I get a 400 error from VBA. I don't know what's wrong with this code.
As an example A2 (and subsequent cells in the A column) look like this:
Sub cleanLoginTime()
Dim cell As Range
Dim MyRange As Range
Dim tmp As String
LastRow = Cells(Rows.Count, 1).End(xlUp)
Set MyRange = ActiveSheet.Range("A2:A" & LastRow) 'this is your range of data
For Each cell In MyRange.Cells
tmp = cell.Value
'output n - 1 characters from the right
cell.Value = Right(tmp, Len(tmp) - 21)
Next
End Sub
Remove Left From Strings in Column
Sub CleanLoginTime()
Const FindString As String = ":"
Dim FindStringLength As Long: FindStringLength = Len(FindString)
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim rg As Range
Set rg = ws.Range("A2", ws.Cells(ws.Rows.Count, "A").End(xlUp))
Dim cell As Range
Dim FindStringPosition As Long
Dim CellString As String
For Each cell In rg.Cells
CellString = CStr(cell.Value)
FindStringPosition = InStr(CellString, FindString)
If FindStringPosition > 0 Then ' string found
cell.Value = Right(CellString, Len(CellString) _
- FindStringPosition - FindStringLength + 1)
'Else ' string not found; do nothing
End If
Next cell
End Sub
To make it more efficient (faster), you could introduce an array (Data), to access the worksheet minimally.
Sub CleanLoginTimeArray()
Const FindString As String = ":"
Dim FindStringLength As Long: FindStringLength = Len(FindString)
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim rg As Range
Set rg = ws.Range("A2", ws.Cells(ws.Rows.Count, "A").End(xlUp))
Dim Data() As Variant: Data = rg.Value ' works only if more than one cell!
Dim r As Long
Dim FindStringPosition As Long
Dim CellString As String
For r = 1 To UBound(Data, 1)
CellString = CStr(Data(r, 1))
FindStringPosition = InStr(CellString, FindString)
If FindStringPosition > 0 Then ' string found
Data(r, 1) = Right(CellString, Len(CellString) _
- FindStringPosition - FindStringLength + 1)
'Else ' string not found; do nothing
End If
Next r
rg.Value = Data
End Sub
I get a run-time error '13' because you need .row in
lastrow = Cells(Rows.Count, 1).End(xlUp).row
Do any of your cells have a length < 21?

Simple loop does not paste ranges correctly

I have a simple loop that should copy ranges form three sheets and stack them on top of each other in another sheet. I define the ranges of each of the three sheets via a cell that counts rows in the Control Sheet.
I do not get an error message, however only the range of the first sheets gets pasted. I troubleshooted already to see if the loop is running until end and indeed it does. I cannot wrap my head around why only the range from the first sheets gets pasted in the final sheet.
Sub Loop()
Dim ws_Sheet As Worksheet, ws As Worksheet
Dim lng_LastRow As Long, lng_LastColumn As Long, lng_LastRowSheet As Long
Dim rng_WorkRange As Range
Dim arrSht, i
Dim counter As Integer
arrSht = Array("a", "b", "c")
Set ws_Sheet = Worksheets("d")
ws_Sheet.Cells.ClearContents
counter = 1
For i = 0 To 2
Set ws = Worksheets(arrSht(i))
lng_LastRow = Worksheets("Control").Range("E" & counter).Value + 1
lng_LastColumn = ws.Cells(1, Columns.Count).End(xlToLeft).Column
lng_LastRowSheet = ws_Sheet.Cells(Rows.Count, 1).End(xlUp).Row
Set rng_WorkRange = ws.Range(ws.Cells(1, 1), ws.Cells(lng_LastRow, lng_LastColumn))
rng_WorkRange.Copy ws_Sheet.Range("A" & lng_LastRowSheet)
counter = counter + 1
Next i
End Sub
The issue is
lng_LastRowSheet = ws_Sheet.Cells(Rows.Count, 1).End(xlUp).Row
is the last used row (the last row that has data).
And then you use that to start pasting
rng_WorkRange.Copy ws_Sheet.Range("A" & lng_LastRowSheet)
so you overwrite the last row of data!
The next free row is lng_LastRowSheet + 1 so you should paste there:
rng_WorkRange.Copy ws_Sheet.Range("A" & (lng_LastRowSheet + 1))
You can also see that in the debug data:
a $A$1:$B$338 to A1
b $A$1:$B$91 to A338
c $A$1:$B$356 to A428
a goes from A1:B338 but you start pasting b in A338 so it overwrites the last row of a.
I gave it a test:
Created worksheet Control with data like
Then created worksheets a, b and c like
with data until row 500 so there is enough.
Then created an empty worksheet d for the output.
And used the following code. Note I have optimized it so it uses meaningful variable names, which is much easier to read, understand and debug.
Option Explicit
Public Sub CopyData()
Dim SheetNames() As Variant
SheetNames = Array("a", "b", "c")
Dim wsDestination As Worksheet
Set wsDestination = ThisWorkbook.Worksheets("d")
wsDestination.Cells.ClearContents
Dim i As Long
For i = 0 To 2
Dim wsSource As Worksheet
Set wsSource = ThisWorkbook.Worksheets(SheetNames(i))
Dim SourceLastRow As Long
SourceLastRow = ThisWorkbook.Worksheets("Control").Range("E" & i + 1).Value + 1
Dim SourceLastColumn As Long
SourceLastColumn = wsSource.Cells(1, wsSource.Columns.Count).End(xlToLeft).Column
Dim DestinationFreeRow As Long
DestinationFreeRow = wsDestination.Cells(wsDestination.Rows.Count, 1).End(xlUp).Row + 1 ' Last used row +1
Dim SourceRange As Range
Set SourceRange = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(SourceLastRow, SourceLastColumn))
SourceRange.Copy wsDestination.Range("A" & DestinationFreeRow)
Next i
End Sub
And I get a perfect output like:
Note that in the output I have hidden some rows so you can see eveything is there. This code perfectly does what it is supposed to.
Stack Ranges (Vertically) From Multiple Worksheets
Sub StackRanges()
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Source
Dim sWorksheetNames() As Variant: sWorksheetNames = VBA.Array("a", "b", "c")
' Lookup (Source Last Row)?
Dim lws As Worksheet: Set lws = wb.Worksheets("Control")
Dim llrCell As Range: Set llrCell = lws.Range("E1")
' Destination
Dim dws As Worksheet: Set dws = wb.Worksheets("d")
dws.UsedRange.ClearContents
Dim dfCell As Range: Set dfCell = dws.Range("A1")
Dim sws As Worksheet
Dim srg As Range
Dim slRow As Long
Dim slColumn As Long
Dim i As Long
' Loop.
For i = 0 To UBound(sWorksheetNames)
Set sws = wb.Worksheets(sWorksheetNames(i))
slRow = llrCell.Value + 1
slColumn = sws.Cells(1, sws.Columns.Count).End(xlToLeft).Column
Set srg = sws.Range("A1", sws.Cells(slRow, slColumn))
srg.Copy dfCell
' If you only need to copy values (since you're using '.ClearContents'),
' instead, use the most efficient:
'dfCell.Resize(srg.Rows.Count, srg.Columns.Count).Value = srg.Value
Set llrCell = llrCell.Offset(1) ' next source last row lookup cell
Set dfCell = dfCell.Offset(srg.Rows.Count) ' next first dest. cell
Next i
End Sub
The counter and the lng_lastRow variable is too messy.
I repaleced some code as follow:
Sub newLoop()
Dim ws_Sheet As Worksheet, ws As Worksheet
Dim lng_LastRow As Long, lng_LastColumn As Long, lng_LastRowSheet As Long
Dim rng_WorkRange As Range, rng_lastRange As Range
Dim arrSht, i
Dim counter As Integer
arrSht = Array("a", "b", "c")
Set ws_Sheet = Worksheets("Control")
ws_Sheet.Cells.ClearContents
For i = 0 To 2
Set ws = Worksheets(arrSht(i))
Set rng_lastRange = ws_Sheet.Cells(Rows.Count, 1).End(xlUp)
lng_LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
lng_LastColumn = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Set rng_WorkRange = ws.Range(ws.Cells(1, 1), ws.Cells(lng_LastRow, lng_LastColumn))
rng_WorkRange.Copy rng_lastRange.Offset(1, 0)
Next i
End Sub

Using single cell in loop as trigger to to copy multiple ranges VBA

The macro is working with hard coded inputs but I need loops for debugging and future growth. I don't know the best way to set this up.
Range("b3:b8:) are the cells I would like to loop over.
If cell.value = 1 then
Set var1 = range("a3:aq3") (* This range always has the same row number as cell in loop*)
Set var2 = range("a9:aq9") (*This range always 6 greater than row of cell in loop.)
End if
Next cell
Thanks
Loop Through Rows of a Range
Option Explicit
Sub LoopThroughRows()
Const srgAddress As String = "A3:AQ8"
Const scCol As Long = 2
Const sCriteria As String = "1"
Dim sws As Worksheet: Set sws = ActiveSheet ' improve, e.g.:
'Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
'Dim sws As Worksheet: Set sws = wb.Worksheets("Sheet1")
Dim srg As Range: Set srg = sws.Range(srgAddress) ' last use of 'sws'
Dim srCount As Long: srCount = srg.Rows.Count
Dim srg1 As Range
Dim srg2 As Range
Dim sCell As Range
Dim sr As Long
For Each sCell In srg.Columns(scCol).Cells ' don't forget '.Cells'!
sr = sr + 1 ' monitoring each range row (not worksheet row)
If CStr(sCell.Value) = sCriteria Then ' also avoiding error values
Set srg1 = srg.Rows(sr)
Set srg2 = srg1.Offset(srCount)
' Continue... e.g.:
Debug.Print sr, sCell.Address(0, 0), _
srg1.Address(0, 0), srg2.Address(0, 0)
Else ' not equal to sCriteria (usually do nothing)
' e.g.:
Debug.Print sr, sCell.Address(0, 0), "Nope."
End If
Next sCell
End Sub
Have you tried using a for loop?
Eg:
For Each Cell in Range("B3:B8")
If Cell.Value = 1 Then
Set var1 = range("a3:aq3")
Else
Set var2 = range("a9:aq9")
End If
Next Cell

select entire row with flexibility

I am looking for a way to select an entire row but skip the first 3 columns of the same row without using 'range()' command. What command can i use?
You can use a combination of Cells and Resize:
Range.Cells Property
Range.Resize Property
Depending on how you ask the question (skip first column or first column is), you can use the combination as follows:
Option Explicit
Sub EntireSkipColumns()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim rng As Range
Dim FR As Long: FR = 2
Dim LR As Long: LR = 10
Dim i As Long
Dim j As Long: j = 3 ' Skip first 3 columns
For i = FR To LR
Set rng = ws.Cells(i, j + 1).Resize(, ws.Columns.Count - j)
With rng
' To check if the range is correct.
Debug.Print .Address(False, False)
' Cycle Interior ColorIndex
'.Interior.ColorIndex = i
End With
Next i
End Sub
Sub EntireFirstColumn()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim rng As Range
Dim FR As Long: FR = 2
Dim LR As Long: LR = 10
Dim i As Long
Dim j As Long: j = 4 ' Use 4 as the first column
For i = FR To LR
Set rng = ws.Cells(i, j).Resize(, ws.Columns.Count - j + 1)
With rng
' To check if the range is correct.
Debug.Print .Address(False, False)
' Cycle Interior ColorIndex
'.Interior.ColorIndex = i
End With
Next i
End Sub
EDIT:
Set rngTarget = rngTarget.Offset(1) is only used to move each result a row below.
Sub QualifyCellsToo()
Dim wsSource As Worksheet: Set wsSource = ThisWorkbook.Worksheets("Sheet1")
Dim wsTarget As Worksheet: Set wsTarget = ThisWorkbook.Worksheets("Sheet2")
Dim rngSource As Range
Dim rngTarget As Range
' This is wrong:
'Worksheets("sheets1").Range(Cells(3, 4), Cells(3, 9)).Copy _
Worksheets("sheets2").Range(Cells(3, 4), Cells(3, 9))
' You have to qualify 'Cells', too:
Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(3, 4), _
Worksheets("Sheet1").Cells(3, 9)).Copy _
Worksheets("Sheet2").Range(Worksheets("Sheet2").Cells(3, 4), _
Worksheets("Sheet2").Cells(3, 9))
' This is a long expression, so using variables is preferred.
Set rngSource = wsSource.Range(wsSource.Cells(3, 4), wsSource.Cells(3, 9))
Set rngTarget = wsTarget.Range(wsTarget.Cells(3, 4), wsTarget.Cells(3, 9))
Set rngTarget = rngTarget.Offset(1)
rngTarget.Resize(10).Clear
' Copy values or formulas and formats using same sized ranges.
rngSource.Copy rngTarget
Set rngTarget = rngTarget.Offset(1)
' Copy values or formulas and formats using only the first cell
' of Target Range.
rngSource.Copy rngTarget.Cells(1)
Set rngTarget = rngTarget.Offset(1)
' Copy values
rngTarget.Value = rngSource.Value
Set rngTarget = rngTarget.Offset(1)
' Copy values using target without '.Value'
rngTarget = rngSource.Value
Set rngTarget = rngTarget.Offset(1)
End Sub

Covert a range to string values using array

I want to convert a range of cells from integer to String. However, since I have so much data, I can't use a standard loop for ranges as it takes too long.
Instead I thought to use the array and convert the desired range(array) into string values.
This is what I tried to do by modifying my standardcode that converts range into string just instead range I would use in the below the array:
Sub CovertToString()
Dim ws As Worksheet
Set ws = Sheets("Sheet1")
Dim sArray As Variant
Dim LastRow As Integer
Dim cell As Variant
With ws
LastRow = .Cells(.rows.Count, 1).End(xlUp).row
sArray = .Range(.Cells(1, 8), .Cells(LastRow, 8))
For Each cell In sArray
cell = "'" & cell.Value
Next
End With
End Sub
Unfortunately, It does not work which I understand as I am not sure how to correct it.
This way will convert the cell formats to Text:
Sub ConvertToString()
Dim ws As Worksheet
Dim LastCell As Range
Dim rCell As Range
Set ws = ThisWorkbook.Worksheets("Sheet1")
With ws
Set LastCell = .Cells(.Rows.Count, 1).End(xlUp).Offset(, 7)
'Convert format to 'Text'
.Range(.Cells(1, 8), LastCell).NumberFormat = "#"
End With
End Sub
This way will copy the range to an array and add a ' to each value before posting back to the sheet:
Sub ConvertToString()
Dim ws As Worksheet
Dim LastCell As Range
Dim vValues() As Variant
Dim R As Long
Set ws = ThisWorkbook.Worksheets("Sheet1")
With ws
'Your code is looking for last cell in column A, so offset to column H once found.
'This is a reference to the last cell, not the row number so can be used in the range.
Set LastCell = .Cells(.Rows.Count, 1).End(xlUp).Offset(, 7)
vValues = .Range(.Cells(1, 8), LastCell).Value
'Add a ' to each value.
For R = 1 To UBound(vValues, 1)
vValues(R, 1) = "'" & vValues(R, 1)
Next R
'Paste back to sheet.
.Range(.Cells(1, 8), LastCell) = vValues
End With
End Sub
Further reading on arrays & worksheets

Resources