I have a string array that i want to insert as a new row at the end of the sheet using xlDown.
Iv'e tried Range("A1:A" & UBound(strArr) + 1) = WorksheetFunction.Transpose(strArr)
But it copies that to a column and not to the lowest row..
Thanks for helping.
You need to Resize the Range to size of the array (you need to modify the Column dimension). Since the array starts at 0, and Column starts at 1 we add 1, so the syntax is: Range("A" & LastRow + 1).Resize(, UBound(strArr) + 1).Value.
Second, LastRow finds the last row with data (in Column A), so we +1 to write the result on the next empty row (1 row below).
Try the code below:
Dim LastRow As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row '<-- get last row in Column A
Range("A" & LastRow + 1).Resize(, UBound(strArr) + 1).Value = WorksheetFunction.Transpose(WorksheetFunction.Transpose(strArr))
Using this, this will ensure you are getting last row of the sheet as anything that is detected will make that the last row.
lastrow = Cells(Rows.Count, 1).End(xlUp).Row + 1
Range("A" & lastrow).Resize(, UBound(strArr)).Value = WorksheetFunction.Transpose(strArr)
Option Explicit
Public Sub TestMe()
Dim strArr As Variant
strArr = Array("a", "b", "c")
Range("A" & last_row + 1 & ":A" & last_row + UBound(strArr) + 1) = WorksheetFunction.Transpose(strArr)
End Sub
Public Function last_row(Optional str_sheet As String, Optional column_to_check As Long = 1) As Long
Dim shSheet As Worksheet
If str_sheet = vbNullString Then
Set shSheet = ThisWorkbook.ActiveSheet
Else
Set shSheet = ThisWorkbook.Worksheets(str_sheet)
End If
last_row = shSheet.Cells(shSheet.Rows.Count, column_to_check).End(xlUp).Row
End Function
The trick is that you should find the last row and then use the size of the array to calculate the size of the new range.
Like this:
Range("A" & last_row + 1 & ":A" & last_row + UBound(strArr) + 1) = WorksheetFunction.Transpose(strArr)
Related
For DurcurrRowIn = 14 To .UsedRange.Row + .UsedRange.Rows.Count - 1
DurcurrRowIn = DurcurrRowIn + 1
Set DurlookFor = wb.ActiveSheet.Cells(currRowIn, "C") ' value to find
Set Durlookforin = wb.ActiveSheet.Range("C" & DurcurrRowIn & ":C500")
On Error Resume Next
DurStart = Application.WorksheetFunction.Index(wb.ActiveSheet.Range("F:F"), WorksheetFunction.Match(DurlookFor, Durlookforin, 0))
DurEnd = Application.WorksheetFunction.Index(wb.ActiveSheet.Range("G:G"), WorksheetFunction.Match(DurlookFor, Durlookforin, 0))
Dur1 = DurEnd - DurStart
Dur = Dur + Dur1
Next
Looking to perform an index/match to grab an employees id on the current row and look for it further down the column not including the row I'm currently in. Once it finds the same employee id, grab the start/end dates and determine their durations, then add that figure to the total duration number (dur). Currently not grabbing the dates, though it did work when my "Durlookforin" was just the whole column C, which doesn't really help. Will post my dimensions below.
Dim DurcurrRowIn As Long
Dim DurcurrColIn As Long
Dim DurcurrRowOut As Long
Dim wb As Workbook
Dim Dur As Long
Dim Dur1 As Long
Dim DurEnd As String
Dim DurStart As String
Dim DurlookFor As Range, Durlookforin As Range
Test File Here
Using Employee ID's as keys to a Dictionary makes it easy to add up the Durations.
Most of this code generates a report but this is all you need to get the Durations by Employee ID's
For x = 14 To lastRow
dicIDs(.Cells(x, "C").Value) = dicIDs(.Cells(x, "C").Value) + .Cells(x, "G").Value - .Cells(x, "F").Value
Next
Sample Data
Result
Sub GetDurations()
Application.ScreenUpdating = False
Const SOURCE_SHEETNAME As String = "Sheet1"
Dim lastRow As Long, x As Long
Dim dicIDs As Object
Set dicIDs = CreateObject("System.Collections.SortedList")
With Worksheets(SOURCE_SHEETNAME)
lastRow = .Range("C" & Rows.Count).End(xlUp).Row
For x = 14 To lastRow
dicIDs(.Cells(x, "C").Value) = dicIDs(.Cells(x, "C").Value) + .Cells(x, "G").Value - .Cells(x, "F").Value
Next
Worksheets.Add
.Range("A14:D" & lastRow).Copy Range("A2")
End With
Columns("D").ClearContents
Range("A1:D1") = Array("LastName", "FirstName", "Employee ID", "Duration")
lastRow = Range("A" & Rows.Count).End(xlUp).Row
Range("A1:C" & lastRow).RemoveDuplicates Columns:=Array(1, 2, 3)
lastRow = Range("A" & Rows.Count).End(xlUp).Row
For x = 2 To lastRow
Cells(x, "D").Value = dicIDs(Cells(x, "C").Value)
Next
Columns.AutoFit
Application.ScreenUpdating = True
End Sub
If you are not familiar with using a Scripting Dictionary then this is a must see Excel VBA Introduction Part 39 - Dictionaries
i want to change the row background color if the date is today ( the dates are in column A starting with A7 ) but it doesn't work. Any help is welcomed. Thank you.
Sub Update_Row_Colors()
Dim LRow As Integer
Dim LCell As String
Dim LColorCells As String
LRow = 7
While LRow < 50
LCell = "A" & LRow
'Color will changed in columns A to AM
LColorCells = "A" & LRow & ":" & "AM" & LRow
Select Case Left(Range(LCell).Value, 6)
Case Now
Range(LColorCells).Interior.ColorIndex = 34
Range(LColorCells).Interior.Pattern = xlSolid
Case Else
Rows(LRow & ":" & LRow).Select
Range(LColorCells).Interior.ColorIndex = xlNone
End Select
LRow = LRow + 1
Wend
End Sub
I think the problem is that you use Now, which returns the current datetime, whilst you're trying to compare this to a date. Try changing:
Case Now
To
Case Date()
You can use date as #Wouter mentioned.
You also need to change your Left(Range(LCell).Value, 6) to Left(Range(LCell).Value, 10)
If you want to use Now then you need to use the Left function as well to remove the time from the Now value.
See below for working answer.
Also remember to always use Long when you want to dimension a variable for referencing a Row or Column
Sub Update_Row_Colors()
'Always want to use a long for referencing a Row or Column
Dim LRow As Long
Dim LCell As String
Dim LColorCells As String
LRow = 7
While LRow < 50
LCell = "A" & LRow
'Color will changed in columns A to AM
LColorCells = "A" & LRow & ":" & "AM" & LRow
Select Case Left(Range(LCell).Value, 10)
Case Left(Now, 10)
Range(LColorCells).Interior.ColorIndex = 34
Range(LColorCells).Interior.Pattern = xlSolid
Case Else
Rows(LRow & ":" & LRow).Select
Range(LColorCells).Interior.ColorIndex = xlNone
End Select
LRow = LRow + 1
Wend
End Sub
Just a extra piece of info, you can shorten/clean you code just by using Rangebetter, see below.
I have included a line to check the used rows, note that even if there is a space " " in the Row is will count it.
Option Explicit
Sub Update_Row_Colors()
Dim LRow As Long
Dim RowRange As Range
Dim LastRow As Long
LastRow = ActiveSheet.Range("A1").SpecialCells(xlCellTypeLastCell).Row
For LRow = 7 To LastRow
Set RowRange = Range(Cells(LRow, "A"), Cells(LRow, "AM"))
If Left(Cells(LRow, "A").Value, 10) = Left(Now, 10) Then
RowRange.Interior.ColorIndex = 34
RowRange.Interior.Pattern = xlSolid
Else
RowRange.Interior.ColorIndex = xlNone
End If
Next LRow
End Sub
I have the below code that works great. It parses through all my sheets and finds the row in column A that I want and pastes it to a specified worksheet. However, I need it to copy the specified row plus the next X number of rows. Can someone help me accomplish this?
Sub FindValues()
Dim ws As Excel.Worksheet
Dim LastRow As Long
Dim i As Integer
For Each ws In Application.ThisWorkbook.Worksheets
LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
i = 1
Do While i <= LastRow
If ws.Range("A" & i).Value = "OwnershipType Ownership Type" Then
ws.Rows(i).Copy Sheets("Summary").Range("A2")
i = i - 1
LastRow = LastRow - 1
End If
i = i + 1
Loop
Next
End Sub
You can amend the range of rows being copied on this line like so:
ws.Rows(i & ":" & i + 3).Copy Sheets("Summary").Range("A2")
If the match was found in row 1 for example, the code would render as ws.Rows(1:4).Copy
I have done some minor modifications. Just added (i + number of rows to be copied). Check the below code:
Used Integer copyrw in the code, you can set this integer to copy the number of rows.
Sub FindValues()
Dim ws As Excel.Worksheet
Dim LastRow As Long
Dim i As Integer
Dim copyrw as Integer
copyrw = 3
For Each ws In Application.ThisWorkbook.Worksheets
LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
i = 1
Do While i <= LastRow
If ws.Range("A" & i).Value = "OwnershipType Ownership Type" Then
ws.Rows(i & ":" & i + copyrw).Copy Sheets("Summary").Range("A2")
i = i - 1
LastRow = LastRow - 1
End If
i = i + 1
Loop
Next
End Sub
I have a large datasheet ("Data") with several houndred rows with years in the first column (Eg 31.12.2013) and various data in the following columns.
I've tried to make a macro that goes through column A and finds every cell containing 31.12.2013 and which does not have a cell containing 31.12.2014 beneath it. For every time it does it should copy the entire row, insert the copied cells in a new row beneath it, and change the date from 31.12.2013 to 31.12.2014.
Since this is the first time I've tried making a macro I have no clue what I'm doing. This is what I got after mixing some code I found online and some code from the built in recorder, hopefully someone can make something that actually does anything:
Sub Nyttaarsregnskap()
Dim searchSheet As Worksheet
Dim currentRow As Long
Dim lastRow As Long
Set searchSheet = Sheets("Data")
Application.ScreenUpdating = False
searchSheet.Activate
lastRow = searchSheet.Cells(Rows.Count, "A").End(xlUp).Row
For currentRow = 1 To lastRow
If InStr(LCase(searchSheet.Cells(currentRow, "A")), "12/31/2013") > 0 Then
If Not InStr(LCase(searchSheet.Cells(currentRow + 1, "A")), "12/31/2014") > 0 Then
searchSheet.Rows(currentRow & ":" & currentRow).Copy
Cells(currentRow + 1, "A").Select
Selection.Insert Shift:=xlDown
Application.CutCopyMode = False
Cells(currentRow + 1, "A").FormulaR1C1 = "12/31/2014"
lastRow = lastRow + 1
End If
End If
Next currentRow
End Sub
try this one:
Sub Nyttaarsregnskap()
Dim searchSheet As Worksheet
Dim currentRow As Long
Dim lastRow As Long
Application.ScreenUpdating = False
Set searchSheet = Sheets("Data")
With searchSheet
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For currentRow = lastRow To 1 Step -1
If Format(.Cells(currentRow, "A"), "mm/dd/yyyy") = Format("12/31/2013", "mm/dd/yyyy") Then
If Not Format(.Cells(currentRow + 1, "A"), "mm/dd/yyyy") = Format("12/31/2014", "mm/dd/yyyy") Then
.Range(currentRow + 1 & ":" & currentRow + 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
.Rows(currentRow & ":" & currentRow).Copy .Cells(currentRow + 1, "A")
.Cells(currentRow + 1, "A").FormulaR1C1 = "12/31/2014"
End If
End If
Next currentRow
End With
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
I have an excel sheet of which the data was jumbled: for example, the data that should have been in Columns AB and AC were instead in Columns B and C, but on the row after. I have the following written which moved the data from B and C to AB and AC respectively:
Dim rCell As Range
Dim rRng As Range
Set rRng = Sheet1.Range("A:A")
i = 1
lastRow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
For Each rCell In rRng.Cells
If rCell.Value = "" Then
Range("AB" & i) = rCell.Offset(0, 1).Value
rCell.Offset(0, 1).ClearContents
End If
i = i + 1
If i = lastRow + 1 Then
Exit Sub
End If
Next rCell
End Sub
However, it doesn't fix the problem of the data being on the row BELOW the appropriate row now that they are in the right columns. I am new to VBA Macros so I would appreciate any help to make the data now align. I tried toggling the Offset parameter (-1,0) but it's not working.
Try something like this?
For i = Lastrow To 1 Step -1
' move data into cell AA from Cell A one row down
Cells(i, 27).Value = Cells(i + 1, 1).Value
Next
You don't need to loop through the range to accomplish what you're trying to do.
Try this instead:
Sub MoveBCtoAbAcUpOneRow()
Dim firstBRow As Integer
Dim lastBRow As Long
Dim firstCRow As Integer
Dim lastCRow As Long
' get the first row in both columns
If Range("B2").Value <> "" Then
firstBRow = 2
Else
firstBRow = Range("B1").End(xlDown).Row
End If
If Range("C2").Value <> "" Then
firstCRow = 2
Else
firstCRow = Range("C1").End(xlDown).Row
End If
' get the last row in both columns
lastBRow = Range("B" & ActiveSheet.Rows.Count).End(xlUp).Row
lastCRow = Range("C" & ActiveSheet.Rows.Count).End(xlUp).Row
' copy the data to the correct column, up one row
Range("B" & firstBRow & ":B" & lastBRow).Copy Range("AB" & firstBRow - 1)
Range("C" & firstCRow & ":C" & lastCRow).Copy Range("AC" & firstCRow - 1)
' clear the incorrect data
Range("B" & firstBRow & ":B" & lastBRow).ClearContents
Range("C" & firstCRow & ":C" & lastCRow).ClearContents
End Sub
Notes:
If the shape of data in each column is the same, you don't need to
find the first and last row for each. You'll only need one variable for each and one copy operation instead of 2.
Make sure you set variable declaration to required.
(Tools -> Options -> Require Variable Declaration) You may already be doing this, but I couldn't tell because it looks like the top of your Sub got truncated.