So, I think I have arrived at a solution for a database index problem, I have been having. It is throwing out claims that have duplicate "TIC" numbers. Of course these duplicates I have are 10 years apart. My solution is to go to the import file, and add a letter to the "TIC" field, e. g. "C" for Canada Claims, "B" for Brazil Claims etc. I need it to populate the correct letter in the "TIC" field, based on the data in the "Country" field. Here is the code I am trying to use now, but it is not working:
Sub AppendToTIC()
Dim d As Range
For Each d In Selection
If d.Value = "Canada" Then e.Value = "C" & e.Value
Next
End Sub
Something is off in my logic, I think, but I am not sure. Any help would be much appreciated.
Thanks
if you are looking to append just the letter to the beginning of the next columns cell then this would work.
Issues you have
You do not define the range of D
you use D to loop through a selection but you necer select anything.
Sub AppendToTIC()
Dim d As Range
Set d = Selection
For Each c In d
c.Offset(0, 1).Value = Left(c.Value, 1) & c.Offset(0, 1).Value
Next
End Sub
Related
So basically, I have a table, where in Column A, I have a repeated list of data with multiple duplicates. In Column B, I have different sets of data related to column A, and then same as Column C. What I wish to have excel do for me is to give me the table (A15:C18), where the Column A data is one cell for each value, and then all the related information is shown right next to it in a concatenated manner.
My approach so far
So basically, what I have done so far is the following approach:
Since Column A are the only thing common in defining the different
lines, so I came up with a way to define each line as a unique line,
using the following =(A1&"--"&countif($A$1:A1;A1). This formula then
helps me identify each row as A--1, A--2, A--3, B--1, B--2 and so
on. Hence I have numbered each data in each row, in a way.
Since I want a unique list, therefore using VBA I get a unique list of variables in a new sheet. Hence, I get the list of just A, B and C in a column instead of them being duplicates.
Once I have the unique list, I then use the =countif() function to count how many times, the variable shows up in the original list (Column A). Like for example, A shows up three times, hence I know that I need to extract 3 rows for this specific data point.
Then using that information, I then proceed to use the =vlookup() function, using the equation =VLOOKUP(A&"--"&1;TABLE;COLUMN)&", "&VLOOKUP(A&"--"&2;TABLE;COLUMN)&", "&VLOOKUP(A&"--"&3;TABLE;COLUMN) .... so on depending on how many times the variable is in the list.
Finally, for example, I then write the vlookup code, and I can then extract all the cells into one place.
PROBLEMS and HELP
So the above approach I have described works on a pilot scale with lots of manual changes for different data points. The problems are the following:
The process of using =vlookup() is based on the =countif() function. I wrote down a very long formula using IF statements saying that =IF(COUNTIF()=1;VLOOKUP(VAR&--&1;TABLE..);IF(COUNTIF()=2;VLOOKUP(VAR&--&1;TABLE..)&","&VLOOKUP(VAR&--&2;TABLE..); ...
Basically, I wrote the IF statement depending on the value of the countIf value. If it is 1, then extract the values for --1, but if it is 2, then do it for --1 and --2, and vice versa. But this is such a bad approach because I can not write this equation for 100 duplicates and if a data point shows up more than 100 Times, then this approach is useless. hence, I would like to know, if it is somehow possible to use a loop VBA code for excel to do a vlookup? So if countif is 4, then do a vlookup from --1 until --4 and so on?
Another limtation is that even though B shows up 2 times in column A, but it only has 1 data point in Column B, and that is the information I need. Hence I should be focusing on that instead of using the =countif() on Column A. **Any suggestions on how I can count, how much information is infront of a data point in the second column? The data in Columns B and C are unique so there are no duplicates. **
I am stuck with the above two points, which kind of makes up the engine of the workbook. So any help or suggestion on how to approach this problem would be greatly appreciated!
Below is the updated image to show the general approach:
Interesting problem, here's my approach.
Pre-requisites:
You need Microsoft Scripting Runtime: Tools -> References -> Microsoft Scripting Runtime -> check the box
There are 2 components of this code.
First the sub you will run:
Sub Concatenate_Data()
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("YourWorksheetsName")
Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim r As Long
Dim dict As New Scripting.Dictionary
Dim letterStr As String
For r = 2 To lastRow
letterStr = ws.Cells(r, 1).Value
If dict.Exists(letterStr) Then
If Not ws.Cells(r, 2).Value = "" Then
dict(letterStr).Candy = dict(letterStr).Candy & ", " & ws.Cells(r, 2).Value
End If
If Not ws.Cells(r, 3).Value = "" Then
dict(letterStr).Juice = dict(letterStr).Juice & ", " & ws.Cells(r, 3).Value
End If
Else
dict.Add letterStr, New Letter
If Not ws.Cells(r, 2).Value = "" Then
dict(letterStr).Candy = ws.Cells(r, 2).Value
End If
If Not ws.Cells(r, 3).Value = "" Then
dict(letterStr).Juice = ws.Cells(r, 3).Value
End If
End If
Next r
Dim k As Variant
r = 2
For Each k In dict.Keys
ws.Cells(r, 5).Value = k
ws.Cells(r, 6).Value = dict(k).Candy
ws.Cells(r, 7).Value = dict(k).Juice
r = r + 1
Next
End Sub
Next is the Class (it is named Letter):
Public Candy As String
Public Juice As String
Here is the input and output I get:
Good Luck!
Without using VBA (I can do it in VBA, but just want to try whether a macro can do it as well, but I haven't figured it out yet),
I have two sheets. Sheet A includes a column of names such as its cell like:
Wright
Sheet B includes a column of names well, but with more letters like title in one cell such as:
Mr. Wright
Sheet A to B is in a relationship of one-to-many (Wright in Sheet A might have multiple rows with Mr.Wright in Sheet B).
If in Sheet B, how to write a macro with some function to achieve: to check whether 'Mr.Wright' has a substring in a cell in Sheet A.
(I think about it might be easier to start from Sheet A: might with regex, find all matches in Sheet B with INDEX or MATCH first. It's much better if it can be done from Sheet B in one shot)
Create a macro called sub_in_name.
Option Explicit
Sub sub_in_name()
Dim x, i As Long
Dim endofcells1, endofcellsmany As Long
endofcells1 = WorksheetFunction.CountA(Range("A:A"))
endofcellsmany = WorksheetFunction.CountA(Range("B:B"))
For x = 1 To endofcells1
For i = 1 To endofcellsmany
If (InStr(1, Cells(i, 2), Cells(x, 1), vbTextCompare)) Then
Cells(i, 2 + x).Value = "True"
Else
Cells(i, 2 + x).Value = "False"
End If
Next i
Next x
End Sub
Intr(start, SearchStr, SearchInStr, vbaoption) is the main function to make this work. Cells(i, 2 + x) is indexed based off the number of non-empty cells in column "A"
Make sure to clear the cells content for each trial; after column "B".
For example put in Column "A" & Column "B" and you will get columns "C:D"
Column "A" Column "B" Column "C" Column "D"
Wright Mr. Wright True False
Roger Wright Jr. True False
Wright the Ivth. True False
Sally False False
Roughly similar logic. Originally I wanted to use existing macro functions to do it. Finally it ended up like making a customized function like below:
Inspired by another thread in stack overflow. I made a code to do full checking like user3553260's. But I think a function is not a bad choice as well, considering if the efficiency is not the top one concern here.
Function LookupName(lookupValue As Variant, lookupRange As Range) As String
Dim r As Long
Dim c As Long
Dim s As String
s = "No"
For r = 1 To lookupRange.Rows.Count
For c = 1 To lookupRange.Columns.Count
If Not IsEmpty(lookupRange.Cells(r, c).Value) Then
If InStr(LCase(lookupValue), LCase(lookupRange.Cells(r, c).Value)) Then
s = "Yes"
Exit For
End If
End If
Next
Next
LookupName = s
End Function
Hello I'm trying to delete all the rows where in column B the members value is over 1000.
I tried this step by step and tried first getting rid of all the unecessary data from B cells and leave just the line with the members.
I noticed there are 5 lines and the members line is the 6'th one. I searched for hours and I still don't get it HOW TO DELETE THE FIRST 5 LINES. Could you please offer me a hand of help? Im sure its soo easy but I cant find it.
I have this:
Option Explicit
Sub Delete5TextLines()
Dim c As Range, s
Application.ScreenUpdating = False
For Each c In Range("B1", Range("B" & Rows.Count).End(xlUp))
**********
Next c
Application.ScreenUpdating = True
End Sub
this is the .csv file:
http://we.tl/vNcyfg9Wus
Alright, this is not very elegant, but the first thing that I came up with, that kinda works.
use this formula to delete the last word in your bulk of text ("members")
Assuming your text is in A1:
=LEFT(A1,FIND("|",SUBSTITUTE(A1," ","|",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))))-1)
This formula gets you the last word of a text, in this case the number of members (because we deleted the word "members)
Assuming you put the formula above in A2
=IF(ISERR(FIND(" ",A2)),"",RIGHT(A2,LEN(A2)-FIND("*",SUBSTITUTE(A2," ","*",LEN(A2)-LEN(SUBSTITUTE(A2," ",""))))))
Now you should have extracted the number of members. If this value is <5000 you can delete the row with a vba loop that should look like this:
Sub deleteRowsAfterMembers
Dim i as Integer
i = ThisWorkbook.Sheets(1).Rows.Count
While i > 0 Do
If (CellWithMemberCount).Value < 5000 Then
ThisWorkbook.Sheets(1).Rows(i).Delete
End If
i = i-1
Loop
End Sub
That'll (hopefully) do it.
Whenever you delete entire rows using a loop, you should start at the bottom of the range and work the loop upwards.
EDIT#1:
Assuming that there are at least five lines within a cell and the lines are separated by Chr(10) then this will remove the first 5 lines:
Sub marine()
ary = Split(ActiveCell.Value, Chr(10))
t = ""
For i = 5 To UBound(ary)
t = t & Chr(10) & ary(i)
Next i
If Len(t) > 1 Then
t = Mid(t, 2)
Else
t = ""
End If
ActiveCell.Value = t
End Sub
I'm trying to filter a table with an advanced filter, in which all items can appear EXCEPT for items with an Article Number that contains (or starts with, it doesn't matter) "PDE", "Q", or "M". The regular Excel filter only allows for two filtering criteria, which is why I need an advanced filter. (To clarify, there are many columns in the table, and Article Number is one of those columns.)
However, I have so far been unable to find a way to filter for items that do NOT contain something, although I've done a fair amount of researching, including the Microsoft tutorial here. Any ideas? Please let me know if you need more information.
My first intuition is that it is not directly possible. I would write a formula like =if(<complex condition>,"Y","N") in an auxiliary column and then filter on that column.
You can do this with AutoFilter You must build an Array of all the elements in the column excluding duplicates and excluding PDE Q and M
Here is an example for column D in which the header row is row #2
Sub FilterExcludeThree()
Dim N As Long, i As Long, c As Collection
Set c = New Collection
N = Cells(Rows.Count, "D").End(xlUp).Row
On Error Resume Next
For i = 3 To N
v = Cells(i, "D").Value
If v = "PDE" Or v = "M" Or v = "Q" Or v = "" Then
Else
c.Add v, CStr(v)
End If
Next
On Error GoTo 0
ReDim ary(0 To c.Count - 1)
For i = 1 To c.Count
ary(i - 1) = c.Item(i)
Next i
ActiveSheet.Range("D2:D" & N).AutoFilter Field:=1, Criteria1:=ary, _
Operator:=xlFilterValues
End Sub
I think the issue might be with having only a single column (though I see no reference to that in the documentation you quote). If your list is in ColumnA, say A7:A17, please try inserting a new ColumnA with say in A2 (A1 blank):
=AND(ISERROR(SEARCH("M",B7)),ISERROR(SEARCH("Q",B7)),ISERROR(SEARCH("PDE",B7)))
then Advanced Filter, List range: $A$6:$B$17, Criteria range: $A$1:$A$2.
SO this started as me trying to help someone else, got stumped. So basically i have values in columns B, C, and D. if have my criteria in H2 and I2 and when my criteria in H2 and I2 matches in B and C then have the corresponding answer in D to populate J2. basically a vlookup with 2 criteria.
i have something like this.
Sub test()
Dim rngCrit1 As Range
Dim rngCrit2 As Range
Dim rngAnswer As Range
Dim strTarget As String
Set rngCrit1 = Range("H2")
Set rngCrit2 = Range("I2")
Set rngAnswer = Range("J2")
Range("B2").Select
strTarget = ActiveCell.Value
Do While strTarget <> ""
With ActiveCell
If strTarget = rngCrit1 Then
If .Offset(0, 1).Value = rngCrit2 Then
rngAnswer.Value = .Offset(0, 2)
Else
.Offset(1, 0).Select
strTarget = ActiveCell.Value
End If
End If
End With
Loop
End Sub
Now this thing just crashes, no debugging or anything. I am self taught so i'm sure i screwed the pooch here somewhere.
*Note this is just to satisfy my own interest not really important, so if it takes you more than 5 min please help someone else that needs it more than I.
Val1 Val2 Val3 Crit1 Crit2 Answer
a r 12 g v 22
b r 14
c s 15
d s 16
e t 18
f t 19
g y 20
g v 22
sample data
It's great that you're trying to improve your VBA skills. The first thing I'd suggest, which will improve any macro you write, is to avoid using .Select. Work directly with the range objects. For instance:
Range("B2").Select
strTarget = ActiveCell.Value
becomes
strTarget = Range("B2").Value
Also, in general, use vbNullString or Len(variable)=0 when checking for "empty" values instead of "". As for why your program is crashing, it may be your use of With. Like Select, it should be avoided in most cases (definitely in this one). Although you update ActiveCell, it's within the scope of the With statement, so once you close it (End With), those changes to ActiveCell are undone (I would suggest stepping through the macro and watch the values of strTarget and ActiveCell). This may not be the case, but I know it holds for other variables, which is why I avoid With (and avoid reassigning values in a With statement)
Anyway, I'd add the following code and rewrite the loop as follows:
Dim r as range
set r = Range("B2") 'keep in mind this range is on the ActiveSheet, so you're better
'off explicitly naming the Sheet e.g. Sheet1.Range("B2")
strTarget1 = Range("B2").Value
strTarget2 = Range("C2").Value
Do While Len(strTarget) <> 0
If strTarget1 = rngCrit1 Then
If strTarget2 = rngCrit2 Then
rngAnswer.Value = r.Offset(0,2)
Exit Do
End If
End If
set r = r.Offset(1,0)
strTarget1 = r.Value
strTarget2 = r.Offset(0,1).Value
Loop
Keep in mind you could also loop with a Long counter i for the row, then call Sheet1.Cells(i,1).Value, Sheet1.Cells(i,2).Value and so on for the values of the different columns of that row (instead of using a range object and .Offset
EDIT: After running your code, the reason for the crash is due to your If statements. You want to go to the next cell regardless. Remove the Else and put the End If statements before the Select. Add an Exit Do after your assignment statement in the 2nd If, since you want to stop looping if your two columns meet the criteria. I've updated my code to show this, as well.
INDEX and MATCH, or SUMPRODUCT tend to work well for this. An example of the former:
http://support.microsoft.com/kb/59482
if you can guarantee val1 and val2 will be unique (e.g. when searching for g & v, there is only 1 line with g and v) then you can use sumifs
I put val1,val2 and val3 in columns A,B, & C, and the search into E,F and the answer in G, and came up with this formula
=SUMIFS(C2:C9,A2:A9,E2,B2:B9,F2)
of course, this fails if val3 is not numeric, or there are more than 1 line with the letters you are looking for