I have an excel file with multiple rows that have the same "Subject ID" with a column (Value A) that will always have the same value by subject ID (or be empty). Example:
╔══════════════════════════╗
║ | subject id | value A | ║
╠══════════════════════════╣
║ |:----------:|---------| ║
║ | 1 | A | ║
║ | 1 | A | ║
║ | 1 | | ║
║ | 1 | | ║
║ | 2 | | ║
║ | 2 | | ║
║ | 2 | B | ║
╚══════════════════════════╝
How can I in Excel create a formula that I can drag down the Value A column such that it gives all of the rows with the same subject ID the same value for Value A? There is no situation in my data in which there would be different values in the Value A column for a particular subject ID: it will either have a value or not.
For example, with this I want to make it so that all of the subjects with an ID of one get a Value A of "A", and for every record with a subject id of 2, I want it to receive a value of "B". Example:
╔══════════════════════════╗
║ | subject id | value A | ║
╠══════════════════════════╣
║ |:----------:|---------| ║
║ | 1 | A | ║
║ | 1 | A | ║
║ | 1 | A | ║
║ | 1 | A | ║
║ | 2 | B | ║
║ | 2 | B | ║
║ | 2 | B | ║
╚══════════════════════════╝
Use Char to convert the number to a char using the ASCII code.
Note, this will only work up to a value of 26, after that you run out of letters and will start getting brackets and other chars
=CHAR(A2+64)
Extending on Dan's solution, this solution should work on more than 26 different IDs
=IF(A1>26,CHAR(QUOTIENT(A1-1,26)+64),"") & CHAR(1+MOD(A1-1,26)+64)
Where A1 has the ID. this formulae gives in the below results
1 A
2 B
.
.
.
26 Z
27 AA
28 AB
29 AC
.
.
.
44 AR
45 AS
.
.
.
53 BA
54 BB
55 BC
Here are my results:
+------------+---------+----------------+
| subject id | value A | Formula result |
+------------+---------+----------------+
| 1 | | Hello |
| 1 | | Hello |
| 1 | Hello | Hello |
| 1 | | Hello |
| 1 | | Hello |
| 1 | | Hello |
| 2 | | B |
| 2 | B | B |
| 2 | B | B |
| 2 | | B |
| 2 | | B |
| 2 | B | B |
| 3 | | World |
| 3 | | World |
| 3 | World | World |
| 3 | | World |
| 3 | | World |
| 4 | | D |
| 4 | D | D |
| 4 | | D |
| 4 | | D |
+------------+---------+----------------+
I built a UDF for it the formula in C2 is =GetCode(A2,$A$2:$A$22,1) where the first parameter is the value to search for, the second is the range to search in and the last is the columns to offset to look for a result.
Code below:
Function GetCode(InputValue As String, SearchRange As Range, ColOffset As Long)
Dim TempVal As String, FirstFoundRow As Long, LastFoundRow As Long, X As Long
On Error Resume Next 'If not found the result will be null
TempVal = Null
If WorksheetFunction.CountIf(SearchRange, InputValue) > 0 Then
FirstFoundRow = SearchRange.Find(InputValue).Row 'Determine the rows to check
LastFoundRow = SearchRange.Find(InputValue, , , , , xlPrevious).Row 'Find the last row, no need to test after that
For X = FirstFoundRow To LastFoundRow 'Loop the checking rows
TempVal = SearchRange.Cells(X, ColOffset + 1).Text 'Assign the value of the offset column for the tested row
If TempVal <> "" Then Exit For 'Quit the loop if it has found the answer
Next
End If
GetCode = TempVal
End Function
Assumption:
subject ID is sorted. If it is not it will give the WRONG results, it would be simple enough for you to modify the code to search through instances in none contiguous data.
note: Please try to format your question with a little more key detail, all the previous answers made the same assumption I did (When you have 1 - A, 2 - B as your sample data it's an easy thing to assume) and also with reference to my above assumption, I had to make the assumption of sorted data as you didn't tell us.
A none code option would have been to take a copy, remove dupes, sort on col B to remove the blanks then use a VLOOKUP formula against the freshly created matrix.
Related
I have 30 peoples waiting for result out of 10. I want to assign each of 30 peoples: 7, 8 or 10 result randomly.
Peoples in excel are:
A1:A30
Random numbers in Excel
B1, C1, D1 //Which means B1=8, C1=7 and D1=10
The random number to keep on:
E1 to E30
To get a random integer in a range, use the randbetween(start,end) function. This will produce a random integer between the start and end parameters inclusively. Since your numbers are not contiguous, you can simply index them and perform a lookup using vlookup(randbetween(startindex,endindex),...) to get a random value from the table.
Check out this Example Excel File I created.
Use the following steps to get your desired result:
List the people in column A
Create a lookup table in Columns G and H
containing your desired result values.
In your result column (column E in the example below), add the formula: =vlookup(randbetween(1,3),G:H,2,false)
Column E will now contain either the numbers 7,8,or 10 for each person.
If you want to generalize this and allow any number of different values in your result lookup table, you can change the formula in column E to: =vlookup(randbetween(1,counta(G:G)-1),G:H,2,false).
Note: The -1 is only needed if your lookup table has a header row.
This will select a random value from all non-empty rows in your result lookup table.
In the example below, I added a header row to row 1, and the people start in row 2, for clarity.
+---+---------+---+---+---+--------+---+-----------+--------------+
| | A | B | C | D | E | F | G | H |
+---+---------+---+---+---+--------+---+-----------+--------------+
| 1 | Names | | | | RESULT | | Result ID | RESULT Value |
+---+---------+---+---+---+--------+---+-----------+--------------+
| 2 | Person1 | | | | 7 | | 1 | 7 |
+---+---------+---+---+---+--------+---+-----------+--------------+
| 3 | Person2 | | | | 7 | | 2 | 8 |
+---+---------+---+---+---+--------+---+-----------+--------------+
| 4 | Person3 | | | | 10 | | 3 | 10 |
+---+---------+---+---+---+--------+---+-----------+--------------+
| 5 | Person4 | | | | 8 | | | |
+---+---------+---+---+---+--------+---+-----------+--------------+
With two sheets, I'm looking to compare columns B and C from Sheet1 to columns A and B of Sheet2. If there is a match, record the value in column A from Sheet1 in column C of Sheet2.
Specifically, what would be a formula to place in Column C on Sheet2 to calculate the corresponding value from Column A on Sheet1?
Sheet1
| A | B | C |
| 1 | 1000 | A |
| 2 | 2000 | B |
| 3 | 3000 | C |
| 4 | 4000 | D |
Sheet2
| A | B | C |
| 3000 | C | |
| 2000 | B | |
| 3000 | C | |
| 1000 | A | |
Sheet2 (desired output)
| A | B | C |
| 3000 | C | 3 |
| 2000 | B | 2 |
| 3000 | C | 3 |
| 1000 | A | 1 |
Apologies if this particular issue has already been answered. I feel like this should be very simple, but I'm just not very experienced in these types of lookups.
The easiest way is to insert a helper column in each sheet that defines a unique key.
To do so, insert a new column C in each sheet and populate it with this formula =A1&";"&B1.
Then, enter this formula in D1 (formerly C1) of sheet 2: =VLOOKUP(C1,Sheet1!$C:$D,2,0)
I am trying to copy data from column E (cost) in sheet1 where the value in column A (code) in sheet2 matches to the value in column A (code) on sheet1.
1
+--------+--------+---------------+---------+--------+
| A | B | C | D | E |
+--------+--------+---------------+---------+--------+
| Code | Name | Description | Price | Cost |
+--------+--------+---------------+---------+--------+
| AC33 | Prod 1 | Prod Desc 1 | 3.99 | 2.00 |
+--------+--------+---------------+---------+--------+
| AC34 | Prod 2 | Prod Desc 2 | 4.99 | 3.00 |
+--------+--------+---------------+---------+--------+
| AC35 | Prod 3 | Prod Desc 3 | 5.99 | 4.00 |
+--------+--------+---------------+---------+--------+
2
+--------+--------+---------------+---------+
| A | B | C | D |
+--------+--------+---------------+---------+
| Code | Name |Updated Price | Cost |
+--------+--------+---------------+---------+
| AC33 | Prod 1 | 16.99 | |
+--------+--------+---------------+---------+
| AC37 | Prod 2 | 18.99 | |
+--------+--------+---------------+---------+
| AC38 | Prod 3 | 21.99 | |
+--------+--------+---------------+---------+
I have used a VLOOKUP but it isn't working, can anyone help please? Am I right in using Vlookup?
This is the formula I am dragging down in column D of sheet2
=VLOOKUP(A2,'1'!$A$2:$A$811,5)
Try this one:
=VLOOKUP(A2,'1'!$A$2:$E$811,5,0)
I changed '1'!$A$2:$A$811 to '1'!$A$2:$E$811 (as mentioned #Jerry in the comment below,
"the table range you're using VLOOKUP on should contain both the column of lookup value and the column containing the result you wish to extract"
) and I also specified last argument of VLOOKUP equals to 0, which says VLOOKUP to find an exact match.
UPD:
As follows up from comments, next formula works for OP:
=VLOOKUP(TRIM(A2),'1'!$A$2:$E$811,5,0)
Below are some of the best practices which resolved the issue.
1) Use the dollar symbol for arguments
2) Provide the complete options
Syntax
VLOOKUP('Lookupvalue','Table Array','Column Index','Range Lookup')
Please note
range_lookup TRUE = approximate match and is by default whereas FALSE = exact match. Please make it false or 0 if you are looking for an exact match.TRUE value relies on your data being sorted in ascending order to work.
Example
VLOOKUP($A1,SheetName!$A:$G,2,0)
Enjoy!!!
I need to sort by columns a ascending, then b ascending, then d ascending and by columns e ascending, then f ascending, then h ascending. Using just QTP, I can't seem to get Excel to sort the data correctly.
What I want:
Table 1:
| a | b | c | d | e | f | g | h |
---------------------------------------------------------------------
| 1 | BE | blank | 51 stuff | 1 | BE | blank | 51 stuff |
| 1 | BE | blank | 100 stuff | 1 | BE | blank | 100 stuff |
| 1 | BE OF A | blank | 121 stuff | 1 | BE OF A | blank | 121 stuff |
| 1 | BE OF A | blank | 200 stuff | 1 | BE OF A | blank | 200 stuff |
| 2 | SEA | blank | 5 stuff | 1 | SEA | blank | 5 stuff |
What I got instead:
Table 2:
| a | b | c | d | e | f | g | h |
---------------------------------------------------------------------
| 1 | BE | blank | 100 stuff | 1 | BE OF A | blank | 121 stuff |
| 1 | BE | blank | 51 stuff | 1 | BE OF A | blank | 200 stuff |
| 1 | BE OF A | blank | 121 stuff | 1 | BE | blank | 100 stuff |
| 1 | BE OF A | blank | 200 stuff | 1 | BE | blank | 51 stuff |
| 2 | SEA | blank | 5 stuff | 1 | SEA | blank | 5 stuff |
Columns e through h gets populated and sorted first. Normally, the cells for those columns are populated in the correct sort order seen in Table 1. However, there have been instances where the sort order is incorrect, but that is rare. Maybe 1 out of 100,000 tries would it be populated with unsorted data.
Columns a through d gets populated and sorted last. The cells for those columns are populated in a somewhat haphazard manner. Table 3 illustrates a very simple end result without forcing a sort.
Table 3:
| a | b | c | d | e | f | g | h |
---------------------------------------------------------------------
| 1 | BE | blank | 100 stuff | 1 | BE | blank | 51 stuff |
| 1 | BE | blank | 51 stuff | 1 | BE | blank | 100 stuff |
| 1 | BE OF A | blank | 121 stuff | 1 | BE OF A | blank | 121 stuff |
| 1 | BE OF A | blank | 200 stuff | 1 | BE OF A | blank | 200 stuff |
| 2 | SEA | blank | 5 stuff | 1 | SEA | blank | 5 stuff |
What's the best way to get QTP and Excel to return the results displayed in Table 1? Is there even a way to?
Snippet of the code(s) that I'm using:
'Some Code Stuff here which leads to exporting the worksheet
rangeOne = "E1:H" & totalRowCnt
Set rangeObj = worksheetOne.Range(rangeOne)
Set range1 = excel1Obj.Range("E1")
Set range2 = excel1Obj.Range("F1")
Set range3 = excel1Obj.Range("H1")
rangeObj.Sort range1, ascend1, range2, ,ascend1, range3, ,ascend1,yes1
'Save worksheet then import sorted data back into Datatable
'and add more Code Stuff here which leads to exporting the worksheet again
rangeOne = "A1:D" & totalRowCnt
Set rangeObj = worksheetOne.Range(rangeOne)
Set range1 = excel1Obj.Range("A1")
Set range2 = excel1Obj.Range("B1")
Set range3 = excel1Obj.Range("D1")
rangeObj.Sort range1, ascend1, range2, ,ascend1, range3, ,ascend1,yes1
'Save worksheet then end script
Try loading the data into a Recordset object. You can sort the recordset like this:
rs.Sort = "a ASC, b ASC, d ASC, e ASC, f ASC, h ASC"
then copy the sorted data to Excel or write them to a CSV.
rs.MoveFirst
Do Until rs.EOF
For i = 0 To rs.Fields.Count - 1
'copy/write rs.Fields(i).Value
Next
rs.MoveNext
Loop
I am trying to create a list from an index of grouped values.
This is very similar to this, however my groups also have "tags" on then that complicate the listings.
Here is an example of my INDEX tab:
| A | B | C | D |
-------------------------
1 | 1 | 1 | 1 | CV |
2 | 1 | 2 | 2 | IS |
3 | 1 | 3 | 3 | IS |
4 | 2 | 4 | 5 | GN |
5 | 2 | 6 | 7 | PS |
6 | 4 | 8 | 11 | SQ |
7 | 2 | 12 | 13 | SS |
8 | 1 | 14 | 14 | AT |
9 | 15 | 15 | 29 | AT |
10| 4 | 30 | 33 | TYP |
Where A is the number of pages, B is the first page, C is the last page and D is the tag. I would also like to add columns such that I can keep a running tally of the tags.
| A | B | C | D | E | F |
---------------------------------------
1 | 1 | 1 | 1 | CV | CV1 | CV1 |
2 | 1 | 2 | 2 | IS | IS1 | IS1 |
3 | 1 | 3 | 3 | IS | IS2 | IS2 |
4 | 2 | 4 | 5 | GN | GN1 | GN2 |
5 | 2 | 6 | 7 | PS | PS1 | PS2 |
6 | 4 | 8 | 11 | SQ | SQ1 | SQ4 |
7 | 2 | 12 | 13 | SS | SS1 | SS2 |
8 | 1 | 14 | 14 | AT | AT1 | AT1 |
9 | 15 | 15 | 29 | AT | AT2 | AT16 |
10| 4 | 30 | 33 | TYP | TYP1 | TYP4 |
Note that the tag could occur multiple times and it may not be in sequential rows.
Here is what I want this to look like for my LIST tab:
| A |
---------
1 | CV1 |
2 | IS1 |
3 | IS2 |
4 | GN1 |
5 | GN2 |
6 | PS1 |
7 | PS2 |
8 | SQ1 |
9 | SQ2 |
10| SQ3 |
11| SQ4 |
and so on...
How do I add the additional columns to the INDEX tab via formulas?
How do I create the LIST via formulas? (...is this even possible?)
The formulas should be pretty simple to write. Just consider what you're trying to accomplish.
Your first formula (in column E) is just taking a running count of the tags (in column D). So you want to count all cells from the first tag up to the corresponding tag where the tag names are the same. That count is to be appended to the tag name.
=$D1 & COUNTIF($D$1:$D1, $D1)
The second formula (in column F) is just taking a running sum of the page counts (in column A). So you want to take the sum of all corresponding page counts from the first tag up to the corresponding tag where the tag names are the same. The sum is to be appended to the tag name.
=$D1 & SUMIF($D$1:$D1, $D1, $A$1:$A1)
Note that the column doesn't change nor does the starting rows of the ranges (hence the need to use absolute ranges). The only thing that changes are the rows of the tag and the row of the end range.
I don't think it would be possible to generate that list through simple formulas. As far as I know, formulas need to have a 1-to-1 correspondence with another range. A single range can yield multiple values so a formula just won't cut it. You'll need to write a VBA script to generate that.
Sub GenerateList()
Dim usedRange As Range
Dim count As Dictionary
Set usedRange = Worksheets("Index").usedRange
Set count = CountValues(usedRange)
Dim output As Range
Dim row As Integer
Dim key As Variant
Set output = Worksheets("List").Columns("A").Rows
output.ClearContents
row = 1
For Each key In count.Keys()
Dim i As Integer
For i = 1 To count(key)
output(row) = key & i
row = row + 1
Next i
Next key
End Sub
Function CountValues( _
usedRange As Range, _
Optional tagsColumn As String = "D", _
Optional valuesColumn As String = "A") As Dictionary
Dim tags As Range
Dim values As Range
Set tags = usedRange.Columns(tagsColumn).Rows
Set values = usedRange.Columns(valuesColumn).Rows
Dim map As New Dictionary
Dim tag As Range
For Each tag In tags
map(tag.Value) = map(tag.Value) + values(tag.row)
Next tag
Set CountValues = map
End Function
This uses a Dictionary so you'll have to reference the scripting runtime.
It sounds like you're just trying to get a list of "Unique Values" on a separate sheet that you can use as your list. Try these pages, there are multiple VBA methods to paste unique items in a range.
Also, Advanced Filter has an option to paste unique values to another location. So none of your repeat tags would appear in this list, only unique ones for your "LIST" tab.
Anyway, not sure if that's what you're wanting, but the question was a smidge vague.
Links here:
Create Unique list
Create Unique list 2