VLOOKUP and search for different n in the same worksheet - excel

[Edited]
I am so sorry I did not describe this very clear:
My question is about the VLookup function:
I used the code like:
B5'n$CX$"
with the intention to let VBA go to the B5 worksheet and also determine which
"n"(either n25 n35 and so on) it has to go to.
This was not working so I am here to seek if I can get any suggestion.
Below is the original post:
I am very newbie in VBA, just started one or two times touching it.
I have modified the code as below, and my objective is to let
VBA find the values for "DI"&i, depending on the values of "DE"&i
in the spreadsheet B5, but in B5, the number "n" which depends on the
values of "CX"&i, and when VBA goes to look up the values of "DE"&i,
it has to determine the value of n firstly with the help of the values
"CX"&i.
The screenshot of the worksheet B5 is as below:
https://www.dropbox.com/s/do6i7zeylaz0sch/B5.jpg?dl=0
My code is as below:
firstly, if "DE"&i >3.9, I would like VBA set "DI"&i = 0,
else with vlookup function.
Thank you very much for any help and advice.
Appreciated.
Sub FindPl()
For i = 2 To 1730
If .Cells("DE" & i).Value > 3.9 Then .Cells("DI" & i).Value = 0
Else: .Cells("DI" & i).Value =
Application.WorksheetFunction.VLookup($DE$" &
i&",'[C:\Users\chenj5\Documents\Meeting_Jan_2019\simulation of Z1.9 for
Ultra Multi-Focal\Meeting 0220\Dataset used for simulation]B5'n$CX$" &
i&", 2, True)
End If
Next cell
Next i
End Sub

Will take a stab at some example code... I guessed on your source data and fixed some syntax errors... spend some time updating and appropriately dimensioning. There is too much going on/wrong with your posted code to provide anything more clear.
Sub FindPl()
dim i as long, wb as workbook, OUTPUTRANGE as range, SEARCHRANGE as range
set wb = "C:\Users\chenj5\Documents\Meeting_Jan_2019\simulation of Z1.9 for Ultra Multi-Focal\Meeting 0220\Dataset used for simulation.xlsx" 'added xlsx extension
with wb
set OUTPUTRANGE = .range(.cells(5,"D"),.cells(100,"D")) 'guessed... the range with the desired output
set SEARCHRANGE = .range(.cells(5,"B"),.cells(100,"B")) 'guessed... the range where you will find .cells(i,"DE")
end with
with activeworkbook.sheets(1) 'FIX THIS TO FIT YOUR NEEDS
For i = 2 To 1730
If .Cells(i, "DE").Value > 3.9 Then 'FIXED SYNTAX ERROR
.Cells(i, "DI").Value = 0
Else:
.Cells(i, "DI").Value = Application.Index(OUTPUTRANGE, Application.Match(.cells(i, "DE").value,SEARCHRANGE, 0))
End If
Next
end with
End Sub

Related

Basic copy loop problem with range & column iteration

how can i turn the following into a 500x loop?
Range("A14:A6368").Cut Range("B1")
Range("B14:B6368").Cut Range("C1")
Range("C14:C6368").Cut Range("D1")
Basically, I copied a table on the web, when I paste into excel, I get it all in 1 column.
Must be simple, but I've spent hours googling and I cannot find the solution!
Thank you!
Something like the following perhaps:
Dim i As Long
For i = 1 To 500
Range(Cells(14, i), Cells(6368, i)).Cut Destination:=Cells(1, i + 1)
Next
You can also use Offset.
Dim i As Long
For i = 0 To 499
Range("A14:A6368").Offset(, i).Cut Destination:=Range("B1").Offset(, i)
Next

MEDIANIFS() in Excel VBA

I'm teaching myself VBA at the moment, & one thing that's really bugged me is that Excel doesn't have MEDIANIFS() function. My research has found:
A MEDIANIF (one condition, not multiple) formula in VBA
The array formula for {MEDIAN(IF(...))}
Putting medians into pivot tables
PS. This is not self study, so posting a solution is fine, but tips are also welcome
Edited version:
My question is, given that I have a MEDIANIF() formula programmed in VBA, how can I modify it to take more than one condition? To turn it into a MEDIANIFS()
> Function MedianIf(rng As Range, Criteria As Variant) As Variant
> Dim cell As Range
> Dim ar() As Variant
> Dim i As Long
>
> With WorksheetFunction
> If .CountIf(rng, Criteria) = 0 Then
> MedianIf = CVErr(2036) '-- #NUM!
> Else
> ReDim ar(1 To rng.Cells.Count)
> For Each cell In rng.Cells
> If .CountIf(cell, Criteria) = 1 Then
> i = i + 1
> ar(i) = cell.Value
> End If
> Next
> MedianIf = .Median(ar)
> End If
> End With End Function
Source: http://www.vbforums.com/showthread.php?650584-RESOLVED-Writing-MedianIf-in-VBA
You could use a parameter array to be able to include multiple criteria. To give you an idea of the mechanics:
Sub MultiCriteria(target As Range, ParamArray Criteria() As Variant)
Dim s As String
Dim i As Long
Dim criterion As Variant
s = target.Address & " to be filtered by:"
For i = LBound(Criteria) To UBound(Criteria)
criterion = Criteria(i)
s = s & vbCrLf & "Criterion " & i & ": " & criterion
Next i
Debug.Print s
End Sub
Sub test()
MultiCriteria Range("A1:B10"), "<5", "<>6", "=C5"
End Sub
Output of test:
$A$1:$B$10 to be filtered by:
Criterion 0: <5
Criterion 1: <>6
Criterion 2: =C5
You could possibly use AND() to gather the criteria into 1, or you can apply the criteria in a loop. I don't have time to develop a complete implementation of MEDIANIF right now but this should get you started. Ask another question if you run into more difficulties.
I think your 2 options are an Array Formula (as suggested in no2) or a User Defined Funtion (UDF) in VBA, but you havent really given us much to go on. Perhaps some sample data and an expected output might help the community more?
Thanks,
Ojf
edit: This might help with the array-formula approach as well...
http://www.mrexcel.com/forum/excel-questions/535743-median-ifs.html

excel vba split text

Please be aware that I am working with a series of ~1000 line medical information databases. Due to the size of the databases, manual manipulation of the data is too time consuming. As such, I have attempted to learn VBA and code an Excel 2010 macro using VBA to help me accomplish parsing certain data. The desired output is to split certain characters from a provided string on each line of the database as follows:
99204 - OFFICE/OUTPATIENT VISIT, NEW
will need to be split into
Active Row Active Column = 99204 ActiveRow Active Column+3 = OFFICE/OUTPATIENT VISIT, NEW
I have researched this topic using Walkenbach's "Excel 2013: Power Programming with VBA" and a fair amount of web resources, including this awesome site, but have been unable to develop a fully-workable solution using VBA in Excel. The code for my current macro is:
Sub EasySplit()
Dim text As String
Dim a As Integer
Dim name As Variant
text = ActiveCell.Value
name = Split(text, "-", 2)
For a = 0 To 1
Cells(1, a + 3).Value = Trim(name(a))
Next a
End Sub
The code uses the "-" character as a delimiter to split the input string into two substrings (I have limited the output strings to 2, as there exists in some input strings multiple "-" characters). I have trimmed the second string output to remove leading spaces.
The trouble that I am having is that the output is being presented at the top of the activesheet, instead of on the activerow.
Thank you in advance for any help. I have been working on this for 2 days and although I have made some progress, I feel that I have reached an impasse. I think that the issue is somewhere in the
Cells(1, a + 3).Value = Trim(name(a))
code, specifically with "Cells()".
Thank you Conrad Frix!
Yah.. funny enough. Just after I post I have a brainstorm.. and modify the code to read:
Sub EasySplit()
Dim text As String
Dim a As Integer
Dim name As Variant
text = ActiveCell.Value
name = Split(text, "-", 2)
For a = 0 To 1
ActiveCell.Offset(0, 3 + a).Value = Trim(name(a))
Next a
End Sub
Not quite the colkumn1,column4 output that I want (it outputs to column3,column4), but it will work for my purpose.
Now I need to incorporate a loop so that the code runs on each successive cell in the column (downwards, step 1) skipping all bolded cells, until it hits an empty cell.
Modified answer to modified request.
This will start on row 1 and continue until a blank cell is found in column A. If you would like to start on a different row, perhaps row 2 if you have headers, change the
i = 1
line to
i = 2
I added a check on the upper bound of our variant before doing the output writes, in case the macro is run again on already formatted cells. (Does nothing instead of erroring out)
Sub EasySplit()
Dim initialText As String
Dim i As Double
Dim name As Variant
i = 1
Do While Trim(Cells(i, 1)) <> ""
If Not Cells(i, 1).Font.Bold Then
initialText = Cells(i, 1).text
name = Split(initialText, "-", 2)
If Not UBound(name) < 1 Then
Cells(i, 1) = Trim(name(0))
Cells(i, 4) = Trim(name(1))
End If
End If
i = i + 1
Loop
End Sub
just add a variable to keep track of the active row and then use that in place of the constant 1.
e.g.
Dim iRow as Integer = ActiveCell.Row
For a = 0 To 1
Cells(iRow , a + 3).Value = Trim(name(a))
Next a
Alternate method utilizing TextToColumns. This code also avoids using a loop, making it more efficient and much faster. Comments have been added to assist with understanding the code.
EDIT: I have expanded the code to make it more versatile by using a temp worksheet. You can then output the two columns to wherever you'd like. As stated in your original question, the output is now to columns 1 and 4.
Sub tgr()
Const DataCol As String = "A" 'Change to the correct column letter
Const HeaderRow As Long = 1 'Change to be the correct header row
Dim rngOriginal As Range 'Use this variable to capture your original data
'Capture the original data, starting in Data column and the header row + 1
Set rngOriginal = Range(DataCol & HeaderRow + 1, Cells(Rows.Count, DataCol).End(xlUp))
If rngOriginal.Row < HeaderRow + 1 Then Exit Sub 'No data
'We will be using a temp worksheet, and to avoid a prompt when we delete the temp worksheet we turn off alerts
'We also turn off screenupdating to prevent "screen flickering"
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'Move the original data to a temp worksheet to perform the split
'To avoid having leading/trailing spaces, replace all instances of " - " with simply "-"
'Lastly, move the split data to desired locations and remove the temp worksheet
With Sheets.Add.Range("A1").Resize(rngOriginal.Rows.Count)
.Value = rngOriginal.Value
.Replace " - ", "-"
.TextToColumns .Cells, xlDelimited, Other:=True, OtherChar:="-"
rngOriginal.Value = .Value
rngOriginal.Offset(, 3).Value = .Offset(, 1).Value
.Worksheet.Delete
End With
'Now that all operations have completed, turn alerts and screenupdating back on
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
You can do this in a single shot without looping using the VBA equivalent of entering this formula, then taking values only
as a formula
=IF(NOT(ISERROR(FIND("-",A1))),RIGHT(A1,LEN(A1)-FIND("-",A1)-1 ),A1)
code
Sub Quicker()
Dim rng1 As Range
Set rng1 = Range([a1], Cells(Rows.Count, "A").End(xlUp))
With rng1.Offset(0, 3)
.FormulaR1C1 = "=IF(NOT(ISERROR(FIND(""-"",RC[-3]))),RIGHT(RC[-3],LEN(RC[-3])-FIND(""-"",RC[-3])-1 ),RC[-3])"
.Value = .Value
End With
End Sub

Hiding Range of Columns in Excel using VBA based on cell Values

I need to hide a range of cells using a macro in excel. C11 contains the column index from where I need to start hiding the columns.
Sub test()
Dim i As Integer
Dim j As Integer
Dim rocket As Range
i = Range("c11").Value
j = 12
rocket = Range(Cells(5, i), Cells(5, j))
Range("Rocket").Select
Selection.EntireColumn.Hidden = True
End Sub
The code is giving some unexpected error and as I am a novice, so have no clue what needs to be done..
Tree steps to make your code working:
1st. Add Set key word in appropriate line which is necessary:
Set rocket = Range(Cells(5, i), Cells(5, j))
2nd. Rocket variable represents range, you will NOT need to call it in this way:
Range("Rocket")....
but
rocket....
3rd. Avoid Select method and Selection object always when possible. Therefore the last two lines replace with this single one (which implements 2nd step, too):
rocket.EntireColumn.Hidden = true
That last answer was awesome! Just for someone else's FYI, here is what worked in Excel 2007. The first line is always 3, but the ending line needed to be a variable. That's where I had the problem. THIS FIXED IT! The last 4 lines before the "End If" do the work. Hope this helps!
Dim RowsToHide As Range
Dim RowHideNum As Integer
' Set Correct Start Dates for Billing in New File
Workbooks("----- Combined_New_Students_Updated.xlsx").Activate
Sheets("2015").Activate
StartDateLine1 = Format(START_DATE_1, "ww") - 1 ' Convert Start Date to Week Number
StartDateLine1 = (StartDateLine1 * 6) - 2 ' Convert Start Date to Line Number
If StartDateLine1 >= "10" Then
Cells(4, "q").Value = ""
Cells(StartDateLine1, "q").Value = STATUS_1
Cells(StartDateLine1, "z").Value = "START DATE " + START_DATE_1
RowHideNum = StartDateLine1 - 2
Set RowsToHide = Range(Cells(3, "a"), Cells(RowHideNum, "ab"))
RowsToHide.Select
RowsToHide.EntireRow.Hidden = True
End If

How to merge multiple Range objects, into one, for use as Chart source

I'm trying to make a chart, with multiple columns as source area.
Basically, I want to select specific columns, where I skip some columns, and merge them all into one range. I've setup a loop, where I create a range, and append it's address to a string, and seperates them with a comma. I'm pretty sure this is how Excel wants it formatted.
BUT, I cannot seem to create a new range from this string.
I hope someone here can help me out.
I would very much like to avoid, having to copy the columns to a new sheet, and just mark it all as a range.
I have the following code, for making the combined range:
'Loops for each number of sections
For Z = 1 To Sheet1.txtNoSections
'Get gauge to use
Section = Workbooks(ThisWorkbook.Name).Worksheets(1).Cells(26 + Z, 6).Value
'Sets varibel for distance from root
Dist = Workbooks(ThisWorkbook.Name).Worksheets(1).Cells(26 + Z, 3).Value
'Get range to use
Set ChartRange = ActiveSheet.Range(ActiveCell, ActiveCell.Offset(rc, Section))
RangeString = RangeString & ChartRange.AddressLocal
If Z <> 1 Then
RangeString = RangeString & ","
End If
Next Z
I have then tried to get a new range with something like this, but no luck.
Dim ActualRange As Range
Set ActualRange = ActiveSheet.Range(RangeString)
When printing the RangeString, it looks like this:
$S$2$V$6181$S$2:$X$6181,$S$2:$Z$6181,$S$2:$AB$6181,$S$2:$AD$6181,$S$2:$AF$6181,$S$2:$AH$6181,$S$2:$AJ$6181,$S$2:$AL$6181,$S$2:$AN$6181,$S$2:$AP$6181,$S$2:$AR$6181,$S$2:$AT$6181,$S$2:$AV$6181,$S$2:$AX$6181,$S$2:$AZ$6181,$S$2:$BB$6181,$S$2:$BD$6181,$S$2:$BF$6181,$S$2:$BH$6181,$S$2:$BJ$6181,$S$2:$BL$6181,$S$2:$BN$6181,$S$2:$BP$6181
Seems like the same union would do.
As discussed in the comments above, the best way to handle this is to use native VBA functions such as Union.
You can find several references on how to use this:
on Daily dose of Excel
on vba Express
even a "better" Union on Chip Pearson's website
Yet, please note that you can answer you own question (it is even highly recommended) and accept it. This way, you can share your knowledge with the community and the way you've solved your issue with your own code.
IMHO, this would be even better than accepting my answer.
Following JMax's guidance, I ended up using Union.
This is the code I ended up with.
The first time through the loop, I set the CombinedRange to my actual range, and the subsequent runs, I union.
For Z = 1 To Sheet1.txtNoSections
'Get gauge to use
Section = Workbooks(ThisWorkbook.Name).Worksheets(1).Cells(26 + Z, 6).Value
'Get range to use
Set ChartRange = ActiveSheet.Range(ActiveCell, ActiveCell.Offset(rc, 0))
Debug.Print "ChartRange(" & Z & "): " & ChartRange.Address
If Z = 1 Then
Set CombinedRange = ChartRange
Else
Set CombinedRange = Union(CombinedRange, ChartRange)
End If
ActiveCell.Offset(0, 5).Activate
Next Z
Debug.Print "Combined: " & CombinedRange.Address

Resources