I have 2 text boxes in a excel (or csv file) as below:
text box 1 contains (#11111,#22222,#33333), text box 2 contains (#55555)
#11111,#22222,#33333 #55555
I want the text between , to be on 3 different rows and repeat the text in 2nd text box so that it looks like below:
#11111 #55555
#22222 #55555
#33333 #55555
I am new to VBA. I am reading about string functions but I can't come up with logic on how to do it.
Any help would be appreciated.
Hi #tim williams - Thanks for the advice. I did manage to write a short code which accomplishes the task but it overwrites the text if I have any in 2nd row and 3rd row.
Sub splitcells()
Dim txt As String
Dim txt2 As String
Dim i As Integer
Dim cell1 As Variant
txt = Range("a1", "A1").Value
cell1 = Split(txt, ",")
For i = 0 To UBound(cell1)
Cells(i + 1, 1).Value = cell1(i)
Next i
txt2 = Range("b1", "b1")
For i = 1 To UBound(cell1)
Cells(i + 1, 2).Value = txt2
Next i
End Sub
Any advice on how to push the data on row 2 downwards .....
I do not know how to give you a hint that would help you adjust your macro so I have coded what I think you are after.
You talk about overwriting data in the 2nd or 3rd row so I assume you have several rows containing data in this format. I have therefore converted your code into a loop that works down column A until it finds a blank row.
I avoid overwriting data below the current row by inserting rows as necessary.
I have changed your code in ways that I believe makes the code more maintainable. I have explained my reasons for
these changes.
I have not explained the new statements I have used. It is generally easy to look up a statement once you know it exists but do ask questions if anything is unclear.
I hope this helps.
Option Explicit
Sub splitcells()
' * With VBA, Integer declares a 16-bit value while Long declares a 32-bit
' value. 16-bit values require special processing and are slower. So
' Long is preferred.
' * I do not like variable names such as i. It does not really matter with
' a tiny macro but with a larger macro it does. It does not matter now
' but it matters when you return to this macro in 6 or 12 months to amend
' it. You want to be able to look at variables and immediately know what
' they are. I have named variables according to my system. I am not
' asking you to like my system but to have a system. I can return to
' macros I wrote years ago and immediately recognise all the variables.
Dim InxSplit As Long
' Dim i As Integer
' * Split returns a string array. A Variant can be hold a string array but
' access is slower. Variants can be very useful but only use then when
' you need the flexibility they offer.
Dim SplitCell() As String
' Dim cell1 As Variant
Dim RowCrnt As Long
' * "Range" operates on the active worksheet. You are relying on the correct
' worksheet being active when the macro is called. Also, when you return
' to the macro in 6 or 12 months will you remember which worksheet is
' supposed to be active. ".Range" operates on the worksheet specified in
' the With statement. It doe not matter which worksheet is active and it
' is absolutely clear which worksheet is the target of this code.
With Worksheets("Sheet1")
RowCrnt = 1 ' The first row containing data.
Do While True
' * I use .Cells(row, column) rather than .Range because it is more
' convenient when you need to change the row and/or column numbers.
' * Note the column value can be a number or a column identifier.
' A = 1, B=2, Z=26, AA = 27, etc. I am not doing arithmetic with
' the columns so I have used "A" and "B" which I find more
' meaningful than 1 and 2.
If .Cells(RowCrnt, "A").Value = "" Then
Exit Do
End If
SplitCell = Split(.Cells(RowCrnt, "A").Value, ",")
If UBound(SplitCell) > 0 Then
' The cell contained a comma so this row is to be spread across
' two or more rows.
' Update the current row
.Cells(RowCrnt, "A").Value = SplitCell(0)
' For each subsequent element of the split value, insert a row
' and place the appropriate values within it.
For InxSplit = 1 To UBound(SplitCell)
RowCrnt = RowCrnt + 1
' Push the rest of the worksheet down
.Rows(RowCrnt).EntireRow.Insert
' Select the appropriate part of the original cell for this row
.Cells(RowCrnt, "A").Value = SplitCell(InxSplit)
' Copy the value from column B from the previous row
.Cells(RowCrnt, "B").Value = .Cells(RowCrnt - 1, "B").Value
Next
End If
RowCrnt = RowCrnt + 1
Loop
End With
End Sub
Related
I am trying to identify a column which has a special sort of string in it. For simplicity of the question here is a small sample size of the column I am working with.
The column contains names of people, but we see some records have a special key id in the last 7 to 8 digits of the cell. The one I am interested in are the ones that start with an uppercase "C" followed by 6 numeric digits.
I am trying to get results similar to this.
Column B (Cab ID) just takes the 7 digits from the right, which is easily done by excel functions in vba. I am trying to get column C (Flag), where I identify whether they are the records that I am interested in, which are the ones which start with an uppercase "C" and are followed by 6 numeric digits. If they are, I mark them down as "Y" else "N".
If any extra details needs to be added, let me know and I will make a quick edit as soon as possible to the question.
Without RegExp
Checks if the first of the last seven chars is capital "C". If so, checks if the last 6 chars are numeric. Only then returns "Y".
The Code
Sub LeftRightArray()
Const cSheet1 As Variant = "Sheet1" ' Sheet Name/Index
Const cFirst As Integer = 2 ' Source First Row
Const cSourceC As Variant = "A" ' Source Column
Const cTargetC As Variant = "B" ' Target Column
Const cSearch As String = "C" ' Search String
Dim lastR As Long ' Source Last Row Number
Dim i As Long ' Array Row Counter
Dim j As Integer
Dim vnt As Variant ' Array
Dim strCompare ' Compare String
' Paste Source Range into Array
With Worksheets(cSheet1)
lastR = .Cells(.Rows.Count, cSourceC).End(xlUp).Row
vnt = .Range(.Cells(cFirst, cSourceC), .Cells(lastR, cSourceC))
End With
' Change data in Array.
For i = 1 To UBound(vnt)
' Check if C is the first char of last 7 chars.
If Left(Right(vnt(i, 1), 7), 1) = cSearch Then
' Check if last 6 chars are numeric.
If IsNumeric(Right(vnt(i, 1), 6)) Then
vnt(i, 1) = "Y"
Else
vnt(i, 1) = "N"
End If
Else ' C is not the first letter of last 7 chars.
vnt(i, 1) = "N"
End If
Next
' Paste Array into Target Range
With Worksheets(cSheet1).Cells(cFirst, cTargetC)
.Resize(UBound(vnt), UBound(vnt, 2)) = vnt
End With
End Sub
Use the following formula in column C:
=IFERROR(IF(AND(MID(A2,FIND("*",A2)+1,1)="C",LEN(A2)-(FIND("*",A2)+1)=6),"Y","N"),"N")
Alternative:
Put this formula in column B
=IFERROR(IF(AND(MID(A2,FIND("*",A2)+1,1)="C",LEN(A2)-(FIND("*",A2)+1)=6),MID(A2,FIND("*",A2)+1,7),""),"")
and this formula in columnC
=IF(LEN(B2)<>0,"Y","N")
You can directly use the below excel formula as well. This formula can be used in VBA code after little modification.
=IF(COUNT(FIND({0,1,2,3,4,5,6,7,8,9},A2))=0,"N",IF(EXACT(LEFT(B2,1),"C"),"Y","N"))
Note: A2 is the cell which contains your data, example: Joe*C5464647. Please refer snapshot.
Excel Snapshot with data
I have created a macro that looks at number in a cell and then copies a group of three columns and inserts them to the right of the group. This all works fine.
I have a formula in a cell after these groups of columns that looks to see if there is a 1 in the cell. the code below is what there would be assuming I created 2 groups.
=IF(AND(H9=1,J9=1),1,0)
I want to be able to automatically add the M9=1,P=1 if I had created four groups.
If someone has the time to help it would be much appreciated.
Sorry, learning as I go on here.
I am creating a matrix where I can build up a number of functions in the columns direction and a number of inputs that effect the functions in the rows direction.
I start off with a 'group' of three columns per function, In my first group G9 is the expected condition, H9 is the result during simulation and I9 is the result during real world tests. I want to be able to say how many functions and inputs there will be and automatically create the matrix.
If I have two functions then there will be two groups of columns from G to L.
After all of the functions I have a check to see if they all passed, with two functions this check would be in M9, where I have the formula =IF(AND(H9=1,K9=1),1,0) that checks to see if there is a 1 in both H9 and K9 and then puts a 1 in M9.
If I had four functions then I would need the check formula of =IF(AND(H9=1,K9=1,N=1,Q=1),1,0) in S1
I want to create the check formula within a loop so that it adds in the correct cells to check.
Hope this explains it a little bit better, but probably not!!
Here is the code so far
Private Sub CommandButton1_Click()
' Copy the template worksheet
Worksheets("ZoneTemplate").Copy After:=Worksheets("ProjectConfig")
' Rename the worksheet to the correct Zone
Sheets("ZoneTemplate (2)").Name = Sheets("ProjectConfig").Range("B9")
' Setup the variables
Dim Loop1 As Integer
Dim MySheet As String
Dim NoOfOutputs As Integer
Dim NoOfColumnsOffset As Integer
Dim Loop2 As Integer
' Get the name of the sheet ready for use in the loop
MySheet = Sheets("ProjectConfig").Range("B9").Value
' Get the number of outputs to add
NoOfOutputs = Sheets("ProjectConfig").Range("E9") - 1
' Loop for the number of safety output functions
For Loop1 = 1 To NoOfOutputs
' select the columns to copy and copy them to buffer
Worksheets(MySheet).Range("G:I").Select
Selection.Copy
' Insert the copied columns infront of J1 and shift everything along to the right
Worksheets(MySheet).Range("J1").Insert Shift:=xlShiftToRight
Next Loop1
End Sub
So this did the trick....
Private Sub CommandButton1_Click()
' Copy the template worksheet
Worksheets("ZoneTemplate").Copy After:=Worksheets("ProjectConfig")
' Rename the worksheet to the correct Zone
Sheets("ZoneTemplate (2)").Name = Sheets("ProjectConfig").Range("B9")
' Setup the variables
Dim Loop1 As Integer
Dim MySheet As String
Dim NoOfOutputs As Integer
Dim NoOfInputs As Integer
Dim NoOfColumnsOffset As Integer
Dim Loop2 As Integer
Dim Loop3 As Integer
Dim loop4 As Integer
Dim SOAddr1 As String
Dim SimAddr As String
MySheet = Sheets("ProjectConfig").Range("B9").Value ' Get the name of the sheet ready for use in the loop
NoOfOutputs = Sheets("ProjectConfig").Range("E9") - 1 ' Get the number of outputs to add
' Loop for the number of safety output functions
For Loop1 = 1 To NoOfOutputs
Worksheets(MySheet).Range("Safety_Output_Function").Select ' select the columns to copy and copy them to buffer
Selection.Copy
Worksheets(MySheet).Range("J7").Insert Shift:=xlShiftToRight ' Insert the copied columns infront of J1 and shift everything along to the right
Next Loop1
' Loop to generate the formula for the Sim Result check
For Loop2 = 1 To (NoOfOutputs) 'Sheets("ProjectConfig").Range("E9")
NoOfColumnsOffset = 8 + (Loop2 * 3) ' Work out the cell number for the new column
SOAddr1 = Cells(9, NoOfColumnsOffset).Address(RowAbsolute:=False, ColumnAbsolute:=False) ' Convert the cell number to a letter reference
SimAddr = SimAddr & "," & SOAddr1 & "=1" ' build the string to add for each column and each time we come round the loop
Next Loop2
' put the new formulas in
Worksheets(MySheet).Cells(9, (NoOfColumnsOffset + 2)).Formula = "=IF(AND(H9=1" & SimAddr & "),1,0)"
' Loop to generate the formula for the Hardware Result check
For Loop3 = 1 To (NoOfOutputs) 'Sheets("ProjectConfig").Range("E9")
NoOfColumnsOffset = 9 + (Loop3 * 3) ' Work out the cell number for the new column
SOAddr1 = Cells(9, NoOfColumnsOffset).Address(RowAbsolute:=False, ColumnAbsolute:=False) ' Convert the cell number to a letter reference
SimAddr = SimAddr & "," & SOAddr1 & "=1" ' build the string to add for each column and each time we come round the loop
Next Loop3
' put the new formulas in
Worksheets(MySheet).Cells(9, (NoOfColumnsOffset + 2)).Formula = "=IF(AND(I9=1" & SimAddr & "),1,0)"
NoOfInputs = Sheets("ProjectConfig").Range("D9") - 1 ' Get the number of Inputs to add
' Loop for the number of safety output functions
For loop4 = 1 To NoOfInputs
Worksheets(MySheet).Range("9:9").Select ' select the columns to copy and copy them to buffer
Selection.Copy
Worksheets(MySheet).Range("A10").Insert Shift:=xlDown ' Insert the copied columns infront of J1 and shift everything along to the right
Next loop4
End Sub
Please click on this link for the image of the excel sheet containing the data:
http://i.stack.imgur.com/Dl1YQ.gif
I have a list of task codes in column A.
During each task I will gain a certain competencies. Each competency listed in column C or E is gained during the tasks listed in columns D and F respectively.
Now I need a formula to tell me on column B (COMPETENCIES), which of the competencies are gained during each task of column A. For example for Task A2 (MSC) I expect to see "Tech1,Tech2,Tech3,Tech4,PS1,PS2,PS3" in column B (B2).
I suppose I should treat task codes in column A as strings that should be looked for in the cell contents of columns D and F and when found in any cell of those columns, the corresponding competency should be copied from the same row on the column to the left of the cell, into column B. And then all these entries should be separated by commas in each cell of column B (if there is more than one competency met during task A2).
Can you help me please?
Many Thanks,
Hamid
I agree with the comments: this is a task for VBA.
I typed your GIF into a worksheet. I have made no attempt to fix what I believe are errors. For example, Column A contains "SEMS" but column D contains "SMES".
Step 1 of the routine below is to work down columns C and D then columns E and F and accumulates the data in an array of structures. The objective is to reverse the relationships to give:
MSC Tech1 Tech2 ...
ATT Tech1 Tech2 ...
: :
The result is them placed in column B.
The first step is quite complicated. I hope I have included enough comments for you to understand my code. Work through it slowly and come back with questions is necessary.
Option Explicit
' VBA as intrinsic data types : string, long, double, etc.
' You can declare an array of longs, say.
' The size of an array can be fixed when it is declared:
' Dim A(1 To 5) As Long
' or it can be declared as dynamic and then resized as necessary:
' Dim A() As Long
' ReDim A(1 to 5) ' Initialise A with five entries
' ReDim Preserve A(1 to 10) ' Preserve the first five entries in A
' ' and add another 5.
'
' Sometimes a more complex structure is required. For this problem we need
' to build a list of Tasks with a list of Competencies against each Task.
' VBA allows us to to define the necessary structure as a "User Type"
' Define a user type consisting of a Task name and an array of Competencies
Type typTaskComp
Task As String
Comp() As String
End Type
' Declare array in which Tasks and Competencies are
' accumulated as a dynamic array of type typTaskComp.
Dim TaskComp() As typTaskComp
Dim InxTaskCrntMax As Long
Sub MatchTaskToCompetencies()
Dim CompListCrnt As String
Dim InxCompCrnt As Long ' Index for Competencies for a Task
Dim InxTaskCrnt As Long ' Index for Tasks
Dim RowCrnt As Long
Dim TaskCrnt As String
ReDim TaskComp(1 To 10) ' Initialise TaskComp for 10 Tasks
InxTaskCrntMax = 0 ' The last currently used row in TaskComp. That
' is, no rows are currently used.
' Load array TaskComp() from the sheet
Call DecodeCompencyTask("Sheet1", 3, 4)
Call DecodeCompencyTask("Sheet1", 5, 6)
' The format and contents of TaskComp is now:
' Competency ...
' Task 1 2 3 4 5 ...
' 1 MSC Tech1 Tech2 Tech3 Tech4 PS1
' 2 ATT Tech1 Tech2 Tech3 Tech4 PS1
' 3 PLCY Tech1 Tech2 Tech4 Tech5 Tech6
' : :
' Display contents of TaskComp() to Immediate window
For InxTaskCrnt = 1 To InxTaskCrntMax
Debug.Print Left(TaskComp(InxTaskCrnt).Task & Space(5), 6);
For InxCompCrnt = 1 To UBound(TaskComp(InxTaskCrnt).Comp)
If TaskComp(InxTaskCrnt).Comp(InxCompCrnt) = "" Then
Exit For
End If
Debug.Print Left(TaskComp(InxTaskCrnt).Comp(InxCompCrnt) & Space(5), 6);
Next
Debug.Print
Next
' Now place lists of Competencies in Column 2 against appropriate Task
RowCrnt = 2
With Worksheets("Sheet1")
TaskCrnt = .Cells(RowCrnt, 1).Value
Do While TaskCrnt <> ""
For InxTaskCrnt = 1 To InxTaskCrntMax
If TaskCrnt = TaskComp(InxTaskCrnt).Task Then
' Have found row in TaskComp that matches this row in worksheet
' Merge list of Competencies into a list separated by commas
CompListCrnt = Join(TaskComp(InxTaskCrnt).Comp, ",")
' Empty entries at the end of TaskComp(InxTaskCrnt).Comp will
' result in trailing commas. Remove them.
Do While Right(CompListCrnt, 1) = ","
CompListCrnt = Mid(CompListCrnt, 1, Len(CompListCrnt) - 1)
Loop
' and place in column 2
.Cells(RowCrnt, 2).Value = CompListCrnt
Exit For
End If
Next
RowCrnt = RowCrnt + 1
TaskCrnt = .Cells(RowCrnt, 1).Value
Loop
End With
End Sub
Sub DecodeCompencyTask(WShtName As String, ColComp As Long, ColTask As Long)
' Sheet WShtName contains two columns numbered ColComp and ColTask, Column
' ColComp contains one Competency per cell. Column ColTask holds a comma
' separated list of Tasks per cell. For each row, the Competency is gained
' by performing any of the Tasks.
' Scan the two columns. If a Task is missing from TaskComp() prepare a row
' for it. Add the Competency to the new or existing row for the Task.
Dim CompCrnt As String
Dim Found As Boolean
Dim InxCompCrnt As Long ' Index for Competencies for a Task
Dim InxTaskCrnt As Long ' Index for Tasks
Dim RowCrnt As Long
Dim TaskCrnt As Variant
Dim TaskList() As String
With Worksheets(WShtName)
RowCrnt = 2
Do While .Cells(RowCrnt, ColComp).Value <> ""
CompCrnt = .Cells(RowCrnt, ColComp).Value ' Extract Competency
' Remove any spaces from Task List and then split it
' so there is one Task per entry in TaskList.
TaskList = Split(Replace(.Cells(RowCrnt, ColTask).Value, " ", ""), ",")
' Process each task in TaskList
For Each TaskCrnt In TaskList
Found = False
' Look for current Task in existing rows
For InxTaskCrnt = 1 To InxTaskCrntMax
If TaskComp(InxTaskCrnt).Task = TaskCrnt Then
Found = True
Exit For
End If
Next
If Not Found Then
' New Task found. Prepare new row with Task but no
' Competencies
InxTaskCrntMax = InxTaskCrntMax + 1
If InxTaskCrntMax > UBound(TaskComp) Then
' No free rows in TaskComp. Add some more rows
ReDim Preserve TaskComp(1 To UBound(TaskComp) + 10)
End If
InxTaskCrnt = InxTaskCrntMax
TaskComp(InxTaskCrnt).Task = TaskCrnt
ReDim TaskComp(InxTaskCrnt).Comp(1 To 5)
' Rely on array entries being initialised to ""
End If
Found = False
' Look for an empty Competency slot in current row of TaskComp
For InxCompCrnt = 1 To UBound(TaskComp(InxTaskCrnt).Comp)
If TaskComp(InxTaskCrnt).Comp(InxCompCrnt) = "" Then
Found = True
Exit For
End If
Next
If Not Found Then
' Row is full. Add some extra entries and set InxCompCrnt to
' first of these new entries.
InxCompCrnt = 1 + UBound(TaskComp(InxTaskCrnt).Comp)
ReDim Preserve TaskComp(InxTaskCrnt).Comp(1 _
To UBound(TaskComp(InxCompCrnt).Comp) + 5)
End If
TaskComp(InxTaskCrnt).Comp(InxCompCrnt) = CompCrnt
InxCompCrnt = InxCompCrnt + 1
Next
RowCrnt = RowCrnt + 1
Loop
End With
End Sub
I was hoping someone would have some insight as to how to approach the following Excel macro requirement.
Starting condition:
Variable number of text values in Column A.
Proposed solution:
I would like to be able to select a variable number of consecutive cells in column A, and then have the text concatenated, separated by a comma and , into a single column adjacent to the top most cell in column B.
Examples:
A2-A4 would be selected on the sheet.
After running the macro, the contents of B2 (Directly adjacent to top of selection) would contain text in the form "A2, A3, A4".
A5-A10 selected:
After running the macro, the contents of B5 (Directly adjacent to top of selection) would contain text in the form "A5, A6, A7, A8, A9, A10".
What is killing me is how to utilize the variablity of multiple selections and additonally, I'm not clear on how to handle looping in Excel macro's. I have a CS degree but I ended up working in Infrastructure so I'm a bit rusty. Is someone could help, this would save me emmense time everyday. Thanks to any responses.
The following code does what you seek. I have not added many comments because I am not sure what level of comments are appropriate. For example, I do not want to explain the purpose of each statement if your CS degree allows you to guess. I also suspect there is more to your question than the obvious. For example, should I have made this a function with the worksheet and row numbers passed as parameters. Please come back with questions and I will improve my answer as necessary.
Option Explicit
Sub JoinCells()
Dim ColFirst As Long
Dim ColLast As Long
Dim JoinedValue As String
Dim RowCrnt As Long
Dim RowFirst As Long
Dim RowLast As Long
RowFirst = Selection.Row ' First row of selection
' Selection.Rows.Count returns the number of rows in the selection.
' Warning! You can fool this code by making multiple selections.
RowLast = RowFirst + Selection.Rows.Count - 1
ColFirst = Selection.Column
ColLast = ColFirst + Selection.Columns.Count - 1
If ColFirst <> 1 Or ColLast <> 1 Then
Call MsgBox("Please select a range within column ""A""", vbOKOnly)
Exit Sub
End If
With Worksheets("xxxxxxx") ' Worksheet of your choice.
JoinedValue = .Cells(RowFirst, "A").Value
For RowCrnt = RowFirst + 1 To RowLast
JoinedValue = JoinedValue & "," & .Cells(RowCrnt, "A").Value
Next
.Cells(RowFirst, "B").Value = JoinedValue
End With
End Sub
I have a sheet1 that has names in column A and I have names in sheet 2 column A. The names are mostly the same, besides a comma or period on sheet 2 and not on sheet 1. I need to match some of the text and take sheet 1 column B and paste to sheet 2 column B.
example:
Sheet 1
A B
Doug, Inc. $12.03
For it all, LLC $4452.03
Go for it, Inc. $235.60
Sheet 2
A B
Doug, Inc - Joe
For it all - Mike
Go for it Inc - Tom
I have code that will match and paste only if the names match exact, before the dash "-".
I need help getting it to match just some of the text, not caring about the comma's or periods.
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim rng1 As Range
Set ws1 = Sheets(1)
Set ws2 = Sheets(2)
Set rng1 = ws2.Range(ws2.[a1], ws2.Cells(Rows.Count, "A").End(xlUp))
With rng1.Offset(0, 1)
.FormulaR1C1 = "=IF(RC[-1]<>"""",IF(NOT(ISERROR(MATCH(LEFT(RC[-1],FIND("" - "",RC[-1])-1),'" & ws1.Name & "'!C[-1],0))),INDEX('" & ws1.Name & "'!C,MATCH(LEFT(RC[-1],FIND("" - "",RC[-1])-1),'" & ws1.Name & "'!C[-1],0)),""""),"""")"
.Value = .Value
End With
I have refactored your formula
It will simplify your code if you use a Named Range for your sheet 1 data. Here I've used the name Data
I've used VLookup rather than Index(Match( to further shorthen the formula
The double Substitute's replace , and . in the lookup range
The formula must be an Array formula for the Substitues to work.
Because of the Substitute the returned value is a string. I've wraqpped the function in a Value to convert back to a number, Remove this if not required.
The lookup value is prepared before the call to VLookup, stripping off the - ... if present
'
.FormulaArray = "=VALUE(VLOOKUP(" & _
"LEFT(RC[-1],IFERROR(FIND("" - "",RC[-1])-1,LEN(RC[-1])))," & _
"SUBSTITUTE(SUBSTITUTE(Data,"","",""""),""."",""""),2,0))"
There is one aspect of your sample data that I am unsure about
For it all - Mike will become For it all.
- This won't match For it all, LLC (which becomes For it all LLC)
Go for it Inc - Tom will become Go for it Inc.
- This will match Go for it, Inc. (which becomes Go for it Inc)
Doug, Inc - Joe will become Doug, Inc.
- This won't match Doug, Inc. (which becomes Doug Inc`)
If you want to ignore , and . in both sheets, use
.FormulaArray = "=VALUE(VLOOKUP(" & _
"SUBSTITUTE(SUBSTITUTE(LEFT(RC[-1],IFERROR(FIND("" - "",RC[-1])-1,LEN(RC[-1]))),"","",""""),""."","""")," & _
"SUBSTITUTE(SUBSTITUTE(Data,"","",""""),""."",""""),2,0))"
I am not sure I understand what you are trying to achieve. I do not understand your code which just seems to clear column B of sheet 2. I do not understand why you are using a macro to set formula.
The code below does what I think you are trying to do. If not, I hope my code gives you enough ideas so you can create the code you seek.
I am guessing you are not that familiar with Excel Basic. Sorry if the following insults your knowledge. I assume you would rather be insulted than confused.
Sub Test2()
' This is revised coding. I had not read the question carefully enough
' so my original code did not do what was required.
Dim Pos2 As Integer ' The 1s and 2s in variable names
Dim RowCrnt As Integer ' identify the variable as being for Sheet1
Dim RowMax As Integer ' or Sheet2. The same row variables are
Dim S1ColAB() As Variant ' used for both sheets.
Dim S2ColAB() As Variant
Dim Value1 As String
Dim Value2 As String
With Sheets("Sheet2")
' I generally use Find instead of End(xlUp) for reasons I no longer
' remember. This searches column A (Columns("A")) for anything ("*")
' starting from cell A1 (Range("A1")) and moving backwards
' (xlPrevious) until it finds a value.
RowMax = .Columns("A").Find("*", .Range("A1"), xlFormulas, , _
xlByRows, xlPrevious).Row
' Range(Cells(A,B),Cells(C,D)) defines a rectangle of cells with Row=A,
' Col=B as top left and Row=C, Col=D as bottom right.
' The following statement loads the contents of a block of cells to a
' variant array. Another question has led to a discussion about the value
' of using variant arrays in this way. I have found that moving values
' from one sheet to another can be very slow so I believe it is useful in
' this situation.
S2ColAB = .Range(.Cells(1, 1), .Cells(RowMax, 2)).Value
' Warning about moving values from a cell into a string or variant variable
' and then from the variable into another cell.
' =========================================================================
' When moving the value from the variable to the cell, Excel will
' misinterpret the value if it can.
'
' For example, if the value is 13/1/11 (13 January 2011 here in England)
' this value will be correctly transferred into the new cell. But if the
' value is 4/1/11 (4 January 2011), Excel will recognise this as a valid
' American date and set the new cell to 1 April 2011. The damage that bug
' caused by corrupting a third my dates! I had tested my code towards the
' end of a month and it worked perfectly until the next month.
'
' In this example, string $12.03 becomes currency 12.03 and displays
' here as £12.03.
End With
With Sheets("Sheet1")
' Load the matching cells from sheet 1
S1ColAB = .Range(.Cells(1, 1), .Cells(RowMax, 2)).Value
End With
With Sheets("Sheet2")
For RowCrnt = 1 To RowMax
' I move the Column A values for matching row from the arrays to string
' variables so I can amend their values without losing the original
' values. This was essential with my original code and I have not
' changed it since I think it makes the code easier to understand and
' probably marginally faster.
Value1 = S1ColAB(RowCrnt, 1)
Value2 = S2ColAB(RowCrnt, 1)
' The following code removes anything following a hyphen from Value 2.
' It then removes all commas and dots from both Value1 and Value2. If
' the final values are the same, it moves the Column B of Sheet1 to
' Sheet2.
Pos2 = InStr(1, Value2, "-")
If Pos2 <> 0 Then
' Pos2 is not zero so extract the portion of Value2 up to the "-"
' and then trim trailing spaces.
Value2 = RTrim(Mid(Value2, 1, Pos2 - 1))
End If
' Replace all commas with nothing.
Value1 = Replace(Value1, ",", "")
' Replace all dots with nothing.
Value1 = Replace(Value1, ".", "")
' Merge the two replaces into a single statement.
Value2 = Replace(Replace(Value2, ",", ""), ".", "")
If Value1 = Value2 Then
' If the modified values are equal, copy the Column 2 (B) from
' Sheet1 to Sheet2.
.Cells(RowCrnt, 2).Value = S1ColAB(RowCrnt, 2)
End If
Next
End With
End Sub
Hope this helps. Come back if I have not explained myself adequately.