I have two sheets in excel, one is an order form the other is a production sheet based off the order form.
I am using VLOOKUP to query the order form for the quantity of a given item ordered.
However, sometimes this quantity is highlighted on the order form, indicating that the item in question actually gets produced 2 extra amounts (for free samples).
So for example, in the production form I have:
ITEM|QUANTITY TO PRODUCE
In the order form I have:
ITEM|QUANTITY TO ORDER
I use VLOOKUP to get the match, and this works, but if a cell in QUANTITY TO ORDER is highlighted yellow, then I need the VLOOKUP value to be added by two.
How can I do this? Is there a way to do this automatically, without a macro? My client doesn't want to be manually activating things, they just expect the sheet to work.
Thank you.
VLOOKUP can't do that. What you need to do, is treat a cell's background color as data... and a cell's background color isn't data.
But... this link explains how to do that and what the implications are.
Create a workbook-scoped name (Ctrl+F3) called BackColor referring to =GET.CELL(63,OFFSET(INDIRECT("RC",FALSE),0,-1)), and then add a column immediately to the right of the column where the user highlights cells, and make that column have a formula such as =BackColor<>0 so that it contains TRUE for any highlighted cell in the column immediately to its left.
Hard-coding the extra 2 units into your formula isn't going to be maintenance-friendly, so enter that 2 in a cell somewhere and define a name called ExtraUnits for it.
Then modify your formula to
=[the original VLOOKUP]+IF([lookup the BackColor Boolean], ExtraUnits, 0)
This will add ExtraUnits to the looked up units, for all highlighted cells.
The only drawback is that, as I said above, a cell's background color isn't data as far as Excel is concerned, so your user must trigger a recalculation - just changing cells' background color will not do that, but pressing F9 will.
The below code was found at http://www.mrexcel.com/forum/excel-questions/215415-formula-check-if-cell-highlighted.html
Function CellColorIndex(InRange As Range, Optional _
OfText As Boolean = False) As Integer
'
' This function returns the ColorIndex value of a the Interior
' (background) of a cell, or, if OfText is true, of the Font in the cell.
'
Application.Volatile True
If OfText = True Then
CellColorIndex = InRange(1,1).Font.ColorIndex
Else
CellColorIndex = InRange(1,1).Interior.ColorIndex
End If
End Function
To use the function:
=IF(CELLCORINDEX(A1,FALSE)>0,1,0)
This lets you check the color of the cell , or the text. But you will need to use the Index-match code found here http://www.mrexcel.com/forum/excel-questions/447723-vlookup-returns-cell-address.html in order to match it up.
Also, like the above answer states, highlighting a cell doesn't count as a data change, so even though you can get this info without a macro, if someone updates the cell's highlight status, it will not update the cells using this formula unless automatically.
Sounds like you may need to rethink the Highlighting being the trigger of the +2 samples. I'm with the above answer that recommends adding a column maybe True/False or Yes/No that is checked to see if they get samples.
What I did is this:
I created a user defined function:
Function getRGB3(rcell As Range, Optional opt As Integer) As Long
Dim C As Long
Dim R As Long
Dim G As Long
Dim B As Long
C = rcell.Interior.Color
R = C Mod 256
G = C \ 256 Mod 256
B = C \ 65536 Mod 256
If opt = 1 Then
getRGB3 = R
ElseIf opt = 2 Then
getRGB3 = G
ElseIf opt = 3 Then
If B <> 0 Then
B = -2
End If
getRGB3 = B + 2
Else
getRGB3 = C
End If
End Function
This made it so all the highlighted cells (in yellow) got a value of 2 when referred to, so on the order form it goes like ITEM|QUANTITY TO ORDER|CUSTOM FUNCTION VALUE| and the third column (custom function) is 2 for each corresponding yellow cell next to it, if not, it is just zero.
Then I do a second VLOOKUP to add the CUSTOM FUNCTION VALUE to the original, and then I have added two. :)
Related
In a workbook I have, users either manually enter an account code or select one from a list and the account codes are placed in column C (C7:C446) in a sheet called "JE". The account codes look like this ####### - ### - ## - ######. In column D (D7:D446) in sheet "JE", there is a formula that captures the last 6 digits of the account code. In a sheet called "required_refs", there is a list of 6 digit codes in column A. If the value in the D column in sheet "JE" equals any of the values in column A of "required_refs" sheet, I would like the value in the D column cell to overwrite the cell value in cell D1 in a separate sheet called "references" (I know that may have been confusing, sorry)
Example: if the value of D25 matches any of the values listed in column A of sheet "required_refs", upon double clicking a red colored F25 cell, put the value of D25 (of sheet "JE"), and put it in cell D1 on sheet "references".
I've taken a crack at it as best I know how. I've placed this code in sheet JE:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim project As Range: Set project = Range("D7:D446")
Dim param As Range: Set param = Worksheets("references").Range("D1").Value
For Each cell In project
If project.Value = Worksheets("required_refs").Range("A:A").Value Then
Call gotoRef_ 'macro that simply selects/navigates to the required_ref sheet
project.Value = param
End If
End Sub
Thanks so much in advance for any suggestions on how to complete this. I can elaborate on this further if needed.
This will do what you want:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Intersect(Target, Range("F7:F446")) Is Nothing Then Exit Sub
Dim varReference As Variant
varReference = Columns("D").Cells(Target.Row).Value2
If Not IsError(Application.Match(varReference, Worksheets("required_refs").Columns("A"), 0)) Then
Worksheets("references").Range("D1").Value = varReference
End If
End Sub
Important Points:
Whenever working with event handlers, always limit the scope of the target range in the first line. Otherwise, it might not work correctly or it could slow done your spreadsheet.
Make sure your JE sheet column D values and required_refs sheet column A values are all either text or numbers. Otherwise the values won't be compared correctly.
Note the usage of Application.Match() instead of WorksheetFunction.Match() to access the worksheet function. This, coupled with the use of a Variant type variable, allows us to trap the error that occurs if the match fails.
You can always do this on the sheet. Consider the MATCH function. See here for how to use MATCH.
Or another great tool if you're searching for something in a table associated with a value in another column (not your case I don't think)--VLOOKUP formula. Place this formula in the D cell of the sheet you want to place the numbers in. VLOOKUP is in the following format:
=vlookup(lookup value,table_array,column index number, [range lookup])
The lookup value is the 6 digit code you're looking for (on the JE sheet)
The table_array is simply selecting the values you want to search for (required_refs sheet)
The column index number would be one, since the table only has 1 column. It's basically the column number of the value you're looking for.
And range lookup is for if you think there might be more than one place where it matches.
For your case I think it would look like this:
=vlookup('JE'!D1,'required_refs'!A1:A,1,FALSE)
Then just lock the values you want to keep and click and drag down.
Explanation for VLOOKUP here
Test case:
Take an empty sheet, and merge the range "D2:F2". You can do this manually.
Then, activate the macro recorder and select the column E by just clicking on the E letter on the top of the spreadsheet. You will get the following:
Columns("E:E").Select
Now, try to run this line of code from the same macro directly: you will see that it selects the three columns D, E and F.
Question:
Is this a bug of the macro recorder? Or, rather, a bug of VBA itself (that detects the merged range in my column and decides to extend the selection even if explicitly asked to select one single column)? How should I do to select only one of the columns on which a merged range lies via VBA code, exactly as I can do manually?
Need:
I have a spreadsheet with year on a line, months on the below line and days on the below line.
Hence, the days are just cells but months and especially years are shared/merged cells among the several days.
My need is just to detect the current day and select the column, in order for the user to see on which day they should look the data at. But, because of the "years" cell widely merged just above, the entire year is selected.
No, this is not a bug.
Why: Try to manually select the range E1 to E5. That is what is going on when you use Columns("E:E").select. Think of it as .Select not selecting the column, but instead selecting each cell from top to bottom.
The .select method isn't something you should depend on. What exactly are you trying to use select for? There is another (quite arguably better way) to do this.
Edit: Also, as my father always says, merged cells shouldn't be used. He uses "center across selection" instead, which looks exactly like a merged cell without any of the seemingly buggy behavior.
Need: I would use the macro to highlight the data... probably with something like this...
Range("E7").Interior.ColorIndex = RGB(0, 0, 0)
I feel that the question is genuine unlike some of the comments here. I will try to explain.
Using the test case from the question, say I want to do some action only on column D (say change its column width), without changing the same for columns E to F. I can do that in excel by selecting column D specifically by pressing on column header (press on that "D" in the column names bar). If we select column using range selection (mouse or keyboard shortcut CTRL+SPACE), it extends the selection to include E and F columns. But if we press that column D on the header, it only selects one column. I expect VBA to do the same.
Sadly, I couldn't find anything to "select" a single column or range which includes cells merging through multiple columns or range. However, I could do the action on that single column.
I tried following that didn't work. And I feel that it should work.
Range("D:D").Select
Didn't work. Extends the selection to include merged cells. I guess, this is okay.
Columns("D").Select
Didn't work. Extends the selection to include merged cells. I feel this is not okay.
Columns("D").EntireColumn.Select
Even this didn't work. This definitely should've.
So finally I directly applied the action without selecting the cells.
Column("D").ColumnWidth = 10
And this did it. Only the column D width was changed, leaving column E and F untouched. Similarly, I could do font change and other actions.
Only drawback is that I have to do all actions individually. So, I use a loop to perform action on the selection.
Something like this:
For Each x in Range("D:D")
x.font.size = 10
x.font.name = "Calibri"
'...and so on...
Next x
You probably know the row in which the days start. Therefore, instead of selecting the entire column, you could define a range starting from the first day row to the last day row and select that range.
REQUIREMENTS:
Your table should have this values and formats
Then you can loop through each column on row 4 -just assumed- and check each value if they match today. Next you can scroll to that cell using Application.Goto.
CODE:
Sub FindToday()
Dim wsTable As Worksheet '<~ worksheet with your table
Set wsTable = Sheet2
Dim Cols As Integer '<~ a variable to loop through columns
With wsTable
For Cols = 1 To .Cells(4, .Cells.Columns.Count).End(xlToLeft).Column + 1
If .Cells(4, Cols).Value = Date Then '<~ check if the date is today
Application.Goto wsTable.Cells(1, Cols), True '<~ scroll to that cell if true
Exit For
End If
Next
End With
End Sub
If you want just to hide the particular column if there is merged cell try not to select the column just use like this for example -- Columns("N").EntireColumn.Hidden = True... This will solve your doubt.
Wording my question is slightly tricky so I've included screen-shots to make this easier. I have 2 separate spreadsheets which are currently not linked together in anyway. What I've been asked to do is:
For the drop-downs which have a * next to them, have this * drop-down get converted into a acronym (I.e. If it's Home Visit *, then this will be converted to HV), and have it automatically entered into Cell Position X. Please refer to Image 1 then Image 2)
So the user would click on Sheet one, select the relevant drop-down field and then assign how much time that task took. The second sheet would then update itself with this information - it would insert the users name, program and activities. This is where it gets very tricky. Based off the drop-down selection, if it is asterisked (*), then based off the field-type it will convert it into a set acronym which would then be placed in one of the data fields based off the entry date that has been provided.
I designed both spread-sheets and they have macros in the background, but I can't seem to work out how to best perform this. Would you suggest a transpose function which checks firstly the date criteria and then an INDEX(MATCH) function to match the criteria against a pre-defined name-range which converts Home Visit etc. to HV automatically? I'm also unsure of how to insert delimiters for each new entry that is read. If anyone can provide help I would be very grateful.
I'm not 100% sure I understand your question, but here goes:
What about adding a Worksheet_Change event to look for changes in the drop-down's cell, and then converting it to an acronym?
Place the following code inside the sheet of interest:
Private Sub Worksheet_Change(ByVal Target As Range)
'If Cell A1 is changed, put the acronym into A2
If Target.Row = 1 And Target.Column = 1 Then
Cells(2, 1) = GetAcronym(Target.Value)
End If
End Sub
Function GetAcronym(TheText As String) As String
Dim result As String
Dim x As Long
'Always grab the first letter
result = Mid(TheText, 1, 1)
'Get the other letters
For x = 2 To Len(TheText) - 1
If Mid(TheText, x, 1) = " " Then result = result & Mid(TheText, x + 1, 1)
Next x
GetAcronym = UCase(result)
End Function
I've got an Excel sheet with my variables listed in column E and their values listed in column G
I would like to test if E contains the word "text" (my variable). If so then I want to replace the corresponding cell in column G with "This is my successful if statement text".
If not -- I want the cell to either be left alone (impossible in excel) or keep the value it originally had (I think the issue is its populated with text not numbers).
So far ive tried
=if(e2="text", "Replace with this", G2)
as well as
=if(e2="text", "replace with this", "")
The top returns a number while the bottom returns an empty cell which deletes the contents I had there.
Any suggestions? I think this can be done with VB but that's out of my league.
The proper way to solve this is as so.
In column H (or any that doesn't contain any information) place the formula
=IF(E2 = "text", "This is the true part", G2) and drag down.
This will test E2 for the word "text" and then replace with "this is true.." If the conditions are not met, the original text from G2 is pulled into the new column.
Once this is complete, the desired results should have taken effect. You can then copy the row and use "Paste Special" and select "Values" from the pop up menu to paste in your new data. Selecting Values allows the user to paste the actual field data, not the formula that generated it!
Try this.
Sub g()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ThisWorkbook.Worksheets("Sheet1") 'change sheet name as applicable
lastRow = ws.Cells(ws.Rows.Count, "E").End(xlUp).Row
For i = 1 To lastRow
With ws
If .Cells(i, 5) = "text" Then
.Cells(i, 7) = "The text you want"
End If
End With
Next
End Sub
It seems like you are trying to get four values from column E that you want to parse (cut up) and place in Column G.
By creating four parses { =mid(e2,16,10), =mid(e3, 9, 15), =mid(e4,5,3), =mid(e5,10,22) } in cells G2, G3, G4, and G5, respectively, you can select the block of four G cells (G2:G5), select the block at the bottom right, and drag it down throughout the file.
Optionally, you can use modulo math and case statements to loop through the file and perform the required function at each point:
myCount = 0
myLoop = 0
endMyLoop = false
range("G2").activate
do
myLoop = myCount mod 4
select case myLoop
case 0
code for description_tag
case 1
code for title_tag
case 2
code for headline
case 3
code for text
end select
if activecell.value = "" then endMyLoop = true
loop until (endMyLoop = true)
You stated that every fourth row the value in E is text. So, it should just be a matter of copying the formula every fourth row or performing your function every fourth iteration (modulo returns the remainder) in the G column.
One other option would be to nest your if loops (=if(e2="text","Its text",if(e2="title_tag","Its a title",if(e2="headline","Its headline","Its description")))) to account for the four different options. Of course you would fill the text with the function that you actually want to perform.
I am trying to do a very simple sum of a column that excludes the colored ones. The column I wish to sum is all my accounts and the green ones represent the paid accounts. I want a sum that represents the "left to pay" value to keep track of my progress without redoing my formula every time. The color is not conditional, nor can it be.
I have 2 functions created already:
Function GetColor(MyCell As Range)
GetColor = MyCell.Interior.ColorIndex
End Function
and
Function PAID(MyCell As Range) As Boolean
If MyCell.Interior.ColorIndex = 50 Then
PAID = True
Else
PAID = False
End If
End Function
So I have already created one column next to my numbers that have the formula (with changing cell number):
=PAID(C13)
and this spits out TRUE or FALSE values that I can then based my SUMIF formula off of, currently I have this (E column containing values from the PAID function, C contains my account values):
=SUMIF(E2:E18,"FALSE",C2:C18)
I would like to see if it's possible to bypass making this extra column and run the function directly in the SUMIF (or maybe another function?) so that all I have to do is color my cell and refresh only one formula.
Using colours as part of the program decision process is not ideal, and is overly complex for a simple task.
But assuming you want this (or have no control over this), and the cells you want to sum are NOT coloured with Interior.ColorIndex = 50 - and assuming your values are in range C2:C18 (or wherever), a VBA function to do this is below.
Use the function as =PAID(C2:C18,50)
Function PAID(MyCells As Range, colour_avoid As Integer) As Double
Dim cc As Range
Dim accumulate As Double
accumulate = 0 'not needed but good practice
For Each cc In MyCells
If (cc.Interior.ColorIndex <> colour_avoid) Then
accumulate = accumulate + cc.Value
End If
Next cc
PAID = accumulate
End Function
To repeat, this function will sum all the cells NOT coloured with a colour.index that you give to it (say, 50).