Copy column data consisting of blank cells - excel

I am into a situation where I need to copy a range from a excel sheet and paste it to another. I have done the following coding which is going well...
Dim mpn As String
mpn = Application.InputBox(prompt:="Input the MPN column name:")
mpn1 = mpn
mpn2 = mpn1 & ":" & mpn
Set currentSheet = wbSource.Worksheets(1)
lastRow1 = currentSheet.Range(mpn1).End(xlDown).Row
ThisWorkbook.Sheets("Sheet2").Range("F2:F" & lastRow1) = currentSheet.Range(mpn2 & lastRow1).Value
This coding goes perfectly well untill there is any blank cell in the column. Can anyone please help me on this particular situation.

Like I mentioned in the comments above, instead of prompting for the column name, use .Find to locate the column name. What if user types Blah Blah in the input box?
Also as mentioned in comments use xlUp rather than xlDown to find the last row to counter for blank cells and other issues you may face. See this
Is this what you are trying? (Untested)
I have commented the code so you should not having a problem understanding it. But if you do then simply post back :)
Sub Sample()
Dim mpnCol As Long
Dim ColName As String, strSearch As String
Dim aCell As Range
Dim wbSource As Workbook
Dim wbInput As Worksheet, currentSheet As Worksheet
'~~> Change this to the Mpn Header
strSearch = "MPN"
'~~> This you have declared in your code
'~~> Change as applicable
Set wbSource = "Someworkbook"
Set currentSheet = wbSource.Worksheets(1)
Set wbInput = ThisWorkbook.Sheets("Sheet2")
With currentSheet
'~~> Search for the mpn header in row 1. Change as applicable
Set aCell = .Rows(1).Find(What:=strSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
'~~> Column Number
mpnCol = aCell.Column
'~~> Converting column number to column name
ColName = Split(.Cells(, mpnCol).Address, "$")(1)
'~~> Getting last row
lRow = .Range(ColName & .Rows.Count).End(xlUp).Row
'~~> Checking for excel versions. Comment this if the copying
'~~> will always happen in xl2007+ versions
If lRow > 65536 Then
MsgBox "Are you trying to copy from xl2007 to xl2003?. The number of rows exceed the row limit"
Exit Sub
End If
wbInput.Range("F2:F" & lRow).Value = .Range(ColName & "2:" & ColName & lRow).Value
Else
MsgBox strSearch & " header not found"
End If
End With
End Sub

To copy an entire column, reference your range with the .Columns() function.
You could use something like:
ThisWorkbook.Sheets("Sheet2").Columns("F") =
currentSheet.Columns(mpn1).Value
Another alternative would be to use the .Copy sub and specify a Destination for the copy:
currentSheet.Columns(mpn1).Copy
Destination:=ThisWorkbook.Sheets("Sheet2").Columns("F")
Application.CutCopyMode = false
This answer assumes both workbooks are saved with the same version of Excel. If one workbook is pre-2007, and one is 2007+, then the max number of rows allowed in a sheet will be different.
In that case, copying the entire column is not an option - check out Siddarth's answer for a longer solution to that extra complication. He checks for different number of rows to prevent the error.

Related

How can I turn a Range ("A1:A11") into (A"1: until empty cell")

I have tried to just set the range to ("A:A") but that makes the table too large and my computer freezes up, I have also tried to input a line like Range("A" & Rows.Count).End(xlUp).Offset(1) but that is not recognized by VBA.
Any help would be appreciated!
You need to first define your last row by referencing the last cell in the column then use .End(xlUp).row to find the last row number. You can then use that row number to build cell references, or even save the range as a range variable like I did:
Sub Last_Row_Example()
Dim LastRow As Long 'Last Row as a long integer
Dim RG As Range 'A range we can reference again and again very easily
'Consider renaming it to something more descriptive.
'for your particular situation
LastRow = Range("A" & Rows.Count).End(xlUp).Row ' Here we store the "LastRow" Number
Set RG = Range("A1:A" & LastRow) ' Here we build a range using the LastRow variable.
RG.Select
Application.CutCopyMode = False
ActiveSheet.ListObjects.Add(xlSrcRange, RG, , xlYes).Name = _
"Table3"
Range("Table3[[#All],[Ticker Name]]").Select
Selection.ConvertToLinkedDataType ServiceID:=268435456, LanguageCulture:= _
"en-US"
End Sub

Copy rows with specific text in a column VBA Excel

I am very new to VBA and all coding so I'm not very good at even the basics yet.
I have a worksheet in excel with about a dozen different business' Balance Sheets. I need to copy all of the the rows in a specific range based on the Asset name in column D. The specific range I need to copy is in between "Securities" and "Derivatives."
I successfully copied all the lines of data in between the first set of "Securities" and "Derivatives" but my For Loop keeps copying the same first range when I need it to move to the next set of "Securities" and "Derivatives" Data.
I have tried and thought maybe adding a variable to my rngA might work? Any help is appreciated.
'''
Sub ChartReference2()
Dim findrow As Long
Dim findrow2 As Long
Dim rngA As Range
For Each cell In ActiveWorkbook.Worksheets("BS growth").Range("A:A")
If cell.Value = "Asset" Then
Worksheets("BS growth").Activate
findrow = Range("D:D").Find("Securities", Range("D3")).Row
findrow2 = Range("D:D").Find("Derivatives", Range("D" & findrow)).Row
Range("D" & findrow & ":D" & findrow2, Selection.End(xlToRight)).Select
Selection.Copy
End If
Next cell
End Sub
'''
Try this - comments in-line
Sub ChartReference2()
Dim ws As Worksheet, assetRow, f1 As Range, f2 As Range
Set ws = ActiveWorkbook.Worksheets("BS growth")
assetRow = Application.Match("Asset", ws.Columns("A"), 0)
If Not IsError(assetRow) Then 'matched a cell in Col A?
With ws.Columns("D")
Set f1 = .Find("Securities", lookat:=xlWhole, after:=.Cells(assetRow - 1), _
SearchDirection:=xlNext)
If Not f1 Is Nothing Then 'found the value?
Set f2 = .Find("Derivatives", lookat:=xlWhole, after:=f1, _
SearchDirection:=xlNext)
If Not f2 Is Nothing Then 'found the value?
ws.Range(f1, f2).Copy 'copy range
End If
End If
End With
End If
End Sub

Find string in one worksheet and select it in another

I've got Workbook where I got names and hours worked of employees. I'm looking for comparing rows in one worksheet (Range B6:CC6) and find it in another with selection on cell with employee name (Range A1:A5000) when I change sheets from 1 to 2.
Tried some Range.Find and others, no idea how to do it
Public Sub FindPosition()
Dim Actcol As Integer, Pos As Range, Name As Range
Actcol = ActiveCell.Column
MsgBox "ActiveCell is" & Actcol
Set Pos = Cells(6, Actcol)
MsgBox Pos
Pos.Select
If Worksheets("Sheet2").Activate Then
Worksheets("Sheet2").Range("A1:AA5100").Select
Set Name = Selection.Find(Pos, LookIn:=xlValues)
End If
End Sub
First, if you want to trigger some macro by activation of Sheet2, you need to handle Activate event of Sheet2. This can be done by declaring subroutine in Sheet module like this.
Private Sub Worksheet_Activate()
'Codes you want to be run when Sheet2 is activated.
End Sub
Second, a simple way to find a cell with specific value is to use WorksheetFunction.Match. For example,
Dim SearchInRange As Range
Set SearchInRange = Range("A1:A5000")
Dim EmployeeName As Variant
EmployeeName = ... 'Actual employee name you want to search
On Error GoTo NotFound
Dim Index As Variant
Index = WorksheetFunction.Match(EmployeeName, SearchInRange, 0)
On Error GoTo 0
SearchInRange.Cells(Index).Select
GoTo Finally
NotFound:
' Handle error
Finally:
Range.Find may also work, but remember it has the side effect of changing the state of "Find and Replace" dialog box.
This may helps you
Option Explicit
Sub test()
Dim i As Long, LastRowA As Long, LastRowB As Long
Dim rngSearchValues As Range, rngSearchArea As Range
Dim ws1 As Worksheet, ws2 As Worksheet
'Set you worksheets
With ThisWorkbook
'Let say in this worksheet you have the names & hours
Set ws1 = .Worksheets("Sheet1")
'Let say in this worksheet you have the list of names
Set ws2 = .Worksheets("Sheet2")
End With
'Find the last row of the column B with the names from the sheet with names & hours
LastRowB = ws1.Cells(ws1.Rows.Count, "B").End(xlUp).Row
'Find the last row of the column A with the names from the sheet with list of names
LastRowA = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
'Set the range where you want to check if the name appears in
Set rngSearchArea = ws2.Range("A1:A" & LastRowA)
'Loop the all the names from the sheet with names and hours
For i = 6 To LastRowB
If ws1.Range("B" & i).Value <> "" Then
If Application.WorksheetFunction.CountIf(rngSearchArea, "=" & ws1.Range("B" & i).Value) > 0 Then
MsgBox "Value appears"
Exit For
End If
End If
Next i
End Sub
Oh right, I found solution. Thanks everyone for help.
Public Sub Position()
Dim Accol As Integer
Dim Pos As Range
Dim name As Range
ActiveSheet.name = "Sheet1"
Accol = ActiveCell.Column
Set Pos = Cells(6, Accol)
Worksheets("Sheet2").Activate
Worksheets("Sheet2").Range("a1:a5000").Select
Set name = Selection.Find(What:=Pos, After:=ActiveCell, LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
name.Select
End Sub
Last thing I would like to do which I cannot solve is where do I write automatically script running when I choose Sheet2?

Compare user input value against dictionary in VBA

My macro needs to do some calculations on rows and import data where the user enters an ID. Main thing it's running on the specified ID because there is some data that needs updating/doublechecking so running running the entire source file is not ideal.
My code basically asks the user to enter an ID as 'criteria', and then this gets compared with a dictionary I created containing all data from the source, the problem is that using dict.Item doesn't really compare IDs though it runs on every single row correctly in the destination sheet.
'dictionary filler
For indexsrsrow = 2 To indexsrslastrow
dict.Add CStr(srcWorksheet.Range("A" & indexsrsrow).Value), indexsrsrow
Next indexsrsrow
dim criteria as string
criteria = inputbox("enter id")
For indexdstrow = 2 To indexlastdstrow
'IF ID EXIST AND ITEM = CRITERIA AND C COLUMN IS EMPTY
If dict.Exist(criteria) And destinerow.Cells(indexdstrow, "C") = "" Then
'STUFF HAPPENS HERE
End If
Next indexdstrow
Set dict = Nothing
Is there other way to compare dictionary items with an specified user input?.
Thanks in advance.
#SiddharthRout Kinda, e.g. Im the user and I need to update the record (row) with id 123 so I run the macro, it asks me for the id that I need to update, I input 123 and when I press enter, in the code it should get the id on the source workbook, grab the data and paste it in the destination workbook where the id is 123. Hope this clarifies. –
I have commented the code so you should not have a problem understanding it. Let me know if this is what you want? If not then post your query and I will look at it when I wake up.
Option Explicit
Sub Sample()
Dim srcWorksheet As Worksheet, destinerow As Worksheet
Dim dict As New Dictionary
Dim lRow As Long, i As Long
'~~> Set your source and destination worksheets
Set srcWorksheet = Sheet1
Set destinerow = Sheet2
'~~> Add items to dict from Source worksheet
With srcWorksheet
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 2 To lRow
dict.Add CStr(.Range("A" & i).Value), i
Next i
End With
'~~> Ask user for the criteria
Dim criteria As String
criteria = InputBox("enter id")
'~~> If user presses cancel or item doesn't
'~~> exists in dictionary then exit sub
If criteria = "" Then Exit Sub
If Not dict.Exists(criteria) Then Exit Sub
Dim rngToCopy As Range, aCell As Range
'~~> Find the id in source so we can identify the
'~~> range to copy
With srcWorksheet
Set aCell = .Range("A1:A" & lRow).Find(What:=criteria, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
'~~> I am ssuming the data that you want to copy
'~~> is in Col B. If not then change as applicable
Set rngToCopy = .Range("B" & aCell.Row)
End If
End With
Set aCell = Nothing
'~~> Find the id in destinations so we can identify the
'~~> range where we need to copy
With destinerow
Set aCell = .Columns(1).Find(What:=criteria, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
'~~> I am ssuming the data WHERE you want to copy
'~~> is in Col C. If not then change as applicable
rngToCopy.Copy .Range("C" & aCell.Row)
End If
End With
End Sub

Excel VBA mark duplicate on colA (work on all worksheet include activesheet)

I'd like to mark duplicate on all Worksheet in Workbook. Below the code mark only duplicate if the duplicate exist on other worksheet.
I'd like to mark them also if them exist on Activesheet.
(much better if it possible to mark on different color if duplicate exist only in Activesheet)
Here's a link for solution on similar case, What I need to solve. [a link](https://stackoverflow.com/a/25252503/5493335) "loops through the values of Col A in the sheet which gets activated and then it searches the Col A of all the remaining worksheets and if it finds the ID then it colors the cell background to red. by Siddhart Rout"
I add only one change to this code to eliminate color on empty rows.
But those code is mark(on red color) only if duplicate is one another Worksheet.
I wonder to makr on diffrent color if I found duplicate on activeworksheet.
I will trying to do myself and change the condition with else but It doesn't work. Could anybody get me some help to solve that issue.
Thanks in advance.
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim lRow As Long, wsLRow As Long, i As Long
Dim aCell As Range
Dim ws As Worksheet
Dim strSearch As String
With Sh
'~~> Get last row in Col A of the sheet
'~~> which got activated
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Remove existing Color from the column
'~~> This is to cater for any deletions in the
'~~> other sheets so that cells can be re-colored
.Columns(1).Interior.ColorIndex = xlNone
'~~> Loop through the cells of the sheet which
'~~> got activated
For i = 1 To lRow
'~~> Store the ID in a variable
strSearch = .Range("A" & i).Value
if strSearch <> "" then 'eliminated color empty cell
'~~> loop through the worksheets in the workbook
For Each ws In ThisWorkbook.Worksheets
'~~> This is to ensure that it doesn't
'~~> search itself
If ws.Name <> Sh.Name Then
'~~> Get last row in Col A of the sheet
wsLRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
'~~> Use .Find to quick check for the duplicate
Set aCell = ws.Range("A1:A" & wsLRow).Find(What:=strSearch, _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
'~~> If found then color the cell red and exit the loop
'~~> No point searching rest of the sheets
If Not aCell Is Nothing Then
Sh.Range("A" & i).Interior.ColorIndex = 3
Exit For
End If
End If
Next ws
End if
Next i
End With
End Sub
I'd go with the following refactoring of your code:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim IDsRng As Range, IDCell As Range
Dim ws As Worksheet
Dim strSearch As String
Dim foundInOtherSheet As Boolean, foundInActiveSheet As Boolean
With Sh
Set IDsRng = .Range("A1", .Cells(.Rows.count, 1).End(xlUp)) '<--| set the IDs range as all column A not empty cells with some "text" content
'~~> Remove existing Color from the column
'~~> This is to cater for any deletions in the other sheets so that cells can be re-colored
.Columns(1).Interior.ColorIndex = xlNone
End With
For Each IDCell In IDsRng '<--| Loop through ID cells (i.e. column A "text" cells of the activated sheet)
'~~> Store the ID in a variable
strSearch = IDCell.Value
foundInActiveSheet = WorksheetFunction.CountIf(IDsRng, strSearch) > 1 '<--| count possible dupes in active sheet
foundInOtherSheet = False '<--| initialize it at every new ID
'~~> loop through the worksheets in the workbook
For Each ws In ThisWorkbook.Worksheets
'~~> This is to ensure that it doesn't search itself
If ws.Name <> Sh.Name Then
With ws
foundInOtherSheet = WorksheetFunction.CountIf(.Range("A1", .Cells(.Rows.count, 1).End(xlUp)), strSearch) > 1
If foundInOtherSheet Then Exit For '~~> If found then color then no point searching rest of the sheets
End With
End If
Next
Select Case True '<--| now act accordingly to where duplicates have been found
Case foundInOtherSheet And Not foundInActiveSheet '<--| if duplicates found in "other" sheets only
IDCell.Interior.ColorIndex = 3 '<--| red
Case foundInOtherSheet And foundInActiveSheet '<--| if duplicates found in "other" sheets and in "active" one too
IDCell.Interior.ColorIndex = 6 '<--| yellow
Case Not foundInOtherSheet And foundInActiveSheet '<--| if duplicates found in "active" sheets only
IDCell.Interior.ColorIndex = 14 '<--| green
End Select
Next
End Sub
remove the If ws.Name <> Sh.Name Then line and end if underneath in line with it.

Resources