Referencing a table to look up values between worksheets in Excel - vba

Ok so here's a doosy of a question:
I work in healthcare, currently I have a workbook that references values using an INDEX:MATCH function based off of a patients name, which I manually enter. I pull 7/10 columns using this method automatically. The 8th column is the generation date of the information and the 9th column is a date/time stamp from another sheet which I enter manually based off of the patient's room number.
Here's the tricky part. The two reports, which I'm pulling from our bed management program Allscripts, don't translate the bed names/numbers the same way. So I created a translation table in a different sheet. My question is this: Is there a way I can use a function like INDEX:MATCH, VLOOKUP or something else within either Excel or VBA to reference my translation table in order to look up the bed name/number and auto fill the information I need?
Spreadsheet looks like this:
https://docs.google.com/spreadsheets/d/1j8b2jZ7ZUzKpmoqoisFBVccDKw_CWDfWCGL_CcO2hCo/edit?usp=sharing
So Column G on the 'Raw Data Page' needs to reference column E from the same page, translate that bed name based off of the 'Bed Translation Page' and then look up the date/time information from the 'Job Activity Detail' page in Column G for that translated bed. The catch is the bed names are repeated over 100k times in my current workbook due to the day by day entry of data (I manually change the search range in the INDEX:MATCH function for each column).
I hope someone can shed some light on this for me, it's been the bane of my existence for nearly two years now! Appreciate any info/help any of you may be able to provide! :)

Great news man, you will not need this so! It pulls in column G from the job activity detail, where the identifier on rawdata page is equal to the identifier on job activity detail and the name is the same on Job Activity Detail and Portal of Entry Detail and the two times in J and M of the respective sheets match.
Option Explicit
Sub bd()
Dim rdsheet As Worksheet, jbsheet As Worksheet, btsheet As Worksheet
Dim bdstr, bdendrow, rng As Range, y, Key, GCell, BdCell
Set rdsheet = Sheets("Raw Data Page")
Set jbsheet = Sheets("Job Activity Detail")
Set btsheet = Sheets("Portal of Entry Detail")
bdstr = rdsheet.Range("G3").Address
bdendrow = rdsheet.Range("A3").End(xlDown).Row
Set rng = rdsheet.Range(bdstr & ":G" & bdendrow)
For Each y In rng
If IsEmpty(y) Then
Key = y.Offset(0, -2).Value
Key = Replace(Key, "-", "")
Set GCell = jbsheet.Range("A:A").Find(what:=Key, LookAt:=xlPart)
Set BdCell = btsheet.Range("B:B").Find(what:=y.Offset(0, -4).Value, LookAt:=xlPart)
If Not GCell Is Nothing And btsheet.Range("J" & BdCell.Row).Value = jbsheet.Range("M" & GCell.Row).Value Then
rdsheet.Range(y.Address) = jbsheet.Range("G" & GCell.Row)
End If
End If
Next y
End Sub

{=INDEX('Job Activity Detail'!$G$106463:$G$106689,MATCH('Raw Data Page'!E15459&H15459,'Job Activity Detail'!$A$106463:$A$106689&'Job Activity Detail'!$M$106463:$M$106689,0))} looking up the value as an array function with multiple match criteria seems to be working! I appreciate the insight Lowpar! :)

Related

VBA: filter data based on cell value and fill in to another sheet

enter image description hereI Have two Excel Sheets ("Record") & ("Register"), " Register" is the database. from this database I need to create Records of each employees based on their employee ID (cell value). i am searching for a VBA code that should give me the training Record a each employee once i have enter their ID in the cell and click "a command button". Attached the Excel screen short for reference.
Steps 1: Enter Employee ID in the "Record" sheet
Step 2: Click command button "Filter" in the Record sheet
Step 3: VBA code to run and filter data from "Register" and fill "Record".
IF i Type another Employee ID in the sheet "Record" , it should ClearContents of the previous query. and produce the data.
Please help me, i am not good in VBA .attached the Excel screen short for reference ( UPDATE on 29/07/2018-Question Solved : sharing the code below; thank you Mr.ComradeMicha for your valuable feedback)
Sub Button2_Click()
'Declare the variables
Dim RegisterSh As Worksheet
Dim RecordSh As Worksheet
Dim EmployeeRange As Range
Dim rCell As Range
Dim i As Long
'Set the variables
Set RegisterSh = ThisWorkbook.Sheets("Register")
Set RecordSh = ThisWorkbook.Sheets("Record")
'Clear old data Record Sheet
RecordSh.Range("A8:F107").ClearContents
Set EmployeeRange = RegisterSh.Range(RegisterSh.Cells(6, 4), RegisterSh.Cells(Rows.Count, 6).End(xlUp))
'I went from the cell row6/column4 (or D6) and go down until the last non empty cell
i = 7
For Each rCell In EmployeeRange 'loop through each cell in the range
If rCell = RecordSh.Cells(4, 2) Then 'check if the cell is equal to "Record"
i = i + 1 'Row number (+1 everytime I found another "Record")
RecordSh.Cells(i, 1) = i - 7 'S No.
RecordSh.Cells(i, 2) = rCell.Offset(0, 2) 'Training name
RecordSh.Cells(i, 3) = rCell.Offset(0, -2) 'End date
RecordSh.Cells(i, 4) = rCell.Offset(0, 6) 'Validity
RecordSh.Cells(i, 5) = rCell.Offset(0, 7) 'Remarks
RecordSh.Cells(i, 6) = rCell.Offset(0, 5) 'Minimal requirement
End If
Next rCell
End Sub
Your code is missing a few essential parts you may want to look into:
It seems to require the user to select a specific row before the macro is started, even though there is a command button to trigger the macro. If the layout stays the same, just use constants to store the row where certain input or lookup fields are located.
ra is used both on the input form and on the lookup sheet. That's asking for trouble... Again, use constants or at least "StartingRow=3" or something similar.
You are correcting your employee number to a format that doesn't fit the data provided in the screenshot. Hopefully just a dummy data issue, but in case you are wondering why you don't find anything ;)
You are typecasting all fields individually. If your layout is always the same, it's much easier to just use the "variant" type for all cell values and make sure you already formatted all columns correctly.
ru is never initialized? It's supposed to be "the next row", why not simply use "ra+1" then instead of ru? Also, TRNRow and RTRNRow are never initialized either.
When you "search" your records, you actually only copy the same row into your results, then "copy next row until employee number is wrong". So this only works for exactly one employee, and even then you only catch the first few trainings. Use the Find function on the employee number cell in the records sheet to find the next row with that id, then copy the row's contents and find next.
I think if you get yourself aquainted with the Find function, you will easily finish this macro on your own. Here's a good guide: https://excelmacromastery.com/excel-vba-find
Good luck!

VBA - Updating Master file from new file

I have a Master file which monitors shipment progress for my company. I update this on a weekly basis with progress on existing shipments (shipments which are already in the master file) and input new shipments. These updates come in the form of a update sheet which is in the same format as the master file. I have automated the input of new shipments, but I am stuck on how I could update the existing shipments progress.
Currently I perform a vlookup manually based off a shipment reference number. This is a pain because there are multiple shipment progress columns and I have to trawl through each new input to remove the vlookup formula.
FOR EXAMPlE: shipment reference is in column "C", shipment pickup is in column "AG", shipment dispatched is in column "AH" and shipment arrived is in column "AI".. and so on. In the master sheet I might have the reference number and pickup date. The update sheet might have the dispatch date for this shipment. I would want to take the dispatch date and copy it into the master file for this shipment.
I essentially want to search for blanks in each column of the master file and copy this data from the update file based on the shipment reference. I cannot copy and past over the master file data because I have added a lot of data manually the previous week which the updated file may not have or agree with.
Thank you for your help
Please see my attempted code:
Sub Eupdatedates()
Dim lr As Long, rw As Long, extRNG As Range
Set wb = Workbooks("masterfile.xlsm")
Set ws = wb.Sheets("RawDATA")
lastRow = ws.Range("B" & ws.Rows.Count).End(xlUp).Row
Set extRNG = Workbooks("updatefile.csv").Worksheets("report").Range("C:AL")
For i = 33 To 38 ' columns which contain dates that need updating
ws.Range("$A$2:$CV$" & lastRow).AutoFilter field:=i, Criteria1:="=" 'filter out cells containing data
lastRow = ws.Range("B" & ws.Rows.Count).End(xlUp).Row ' find last row after filtering
firstRow = Range("Cells(2,i): Column(i)" & Rows.Count).Cells.SpecialCells(xlCellTypeBlanks).Row ' indentify first row after filtering
For rw = firstRow To lastRow ' loop through each each empty row cell and perform a vlookup to the update file
Cells(rw, i) = Application.VLookup(Cells(rw, i), extRNG, i - 2, False)
Next rw
Next i
End Sub
I am getting the error with "Range("Cells(2,i): Column(i)" I think I have looked online and cannot seem to find a way to define the range within a for loop. I am new to VBA so a lot of ground to make up. Any thoughts would be greatly appreciated!!
This is a job for VBA. I have done something similar in the past and used VBA to complete the task but it's not something I could code without having the workbooks in front of me. As a pointer I usually start with a big sheet of blank paper and write out the process in logical steps before beginning to code, e.g.
How many rows are there? (I want to know when to stop)
Where is the update sheet and what is it called?
start with first row (row number = 1)
What is the shipment reference (ship ref)?
select cell (row number, column of interest number)
is it blank? YES - find corresponding value in update sheet based on ship ref and update, NO - move to next column of interest
No more columns of interest for this row? - move to next row (row number +1)
etc.

How to delete unselected columns from range

I am new to VBA and am trying to delete unwanted columns loaded from a .csv file. I am importing a large amount of data but then I ask the user what columns they want to keep going by "ID num.". There are a lot of columns with different ID no. and I want to ask the user what they want to keep and delete the rest.
The problem is I need to delete all the other columns the user didn't want but I still need to keep the first 6 columns and the last two columns as that is different information.
Here is what I have so far:
Sub Select()
'the below will take the users inputs
UserValue = InputBox("Give the ID no. to keep seperating with a comma e.g"12,13,14")
'the below will pass the user inputs to the example to split the values
Call Example(UserValue)
End Sub
Sub Example(UserValue)
TestColArray() = Split(UserValue, ",")
For Each TestCol In TestColArray()
' keep all the columns user wants the delete the rest except the first 6 columns and last 2
Next TestCol
End Sub
That is what I have so far, it is not much but the user could put in a lot of columns with different ID number in the input box the way the Excel sheet is laid out all the ID no.s are in row 2 and the first 6 and last 2 columns are blank of row 2 since the ID no. does not apply. I hope that helps.
try this (commented) code:
Option Explicit '<--| use this statament: at the cost of having to declare all used variable, your code will be much easier to debug and maintainable
Sub MySelect()
Dim UserValue As String
'the below will take the users inputs
UserValue = Application.InputBox("Give the ID no. to keep seperating with a comma e.g: ""12,13,14""", Type:=2) '<--| use Type:=2 to force a string input
'the below will pass the user inputs to the example to split the values
Example UserValue '<--| syntax 'Call Example(UserValue)' is old
End Sub
Sub Example(UserValue As String)
Dim TestCol As Variant
Dim cellsToKeep As String
Dim firstIDRng As Range, lastIDRng As Range, IDRng As Range, f As Range
Set firstIDRng = Range("A2").End(xlToRight) '<-- first ID cell
Set lastIDRng = Cells(2, Columns.Count).End(xlToLeft) '<-- last ID cell
Set IDRng = Range(firstIDRng, lastIDRng) '<--| IDs range
cellsToKeep = firstIDRng.Offset(, -6).Resize(, 6).Address(False, False) & "," '<--| initialize cells-to-keep addresses list with the first six blank cells at the left of first ID
For Each TestCol In Split(Replace(UserValue, " ", ""), ",") '<--| loop through passed ID's
Set f = IDRng.Find(what:=TestCol, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False) '<--| search for the current passed IDs range
If Not f Is Nothing Then cellsToKeep = cellsToKeep & f.Address(False, False) & "," '<--| if the current ID is found then update cells-to-keep addresses list
Next TestCol
cellsToKeep = cellsToKeep & lastIDRng.Offset(, 1).Resize(, 2).Address(False, False) '<--| finish cells-to-keep addresses list with the firts two blank cells at the right of last ID
Range(cellsToKeep).EntireColumn.Hidden = True '<-- hide columns-to-keep
ActiveSheet.UsedRange.EntireColumn.SpecialCells(xlCellTypeVisible).EntireColumn.Delete '<--| delete only visible rows
ActiveSheet.UsedRange.EntireColumn.Hidden = False '<-- unhide columns
End Sub
it's assumed to be working with currently active worksheet
A simple google search produces this. On the first page of results too. Perhaps this will suit your needs.
If the data set that needs to be deleted is really large (larger than the ranges you want to keep too.) Then perhaps only select the columns you want to have whilst you import the csv? This stackoverflow question shows how to import specific columns.
EDIT:
So from what I believe the OP is stating as the problem, there is a large csv file that is being imported into excel. After importing there is alot of redundant columns that should be deleted. My first thought would be to only import the needed data (columns) in the first place. This is possible via VBA by using the .TextToColumns method with the FieldInfo argument. As stated above, the stackoverflow question linked above provides a means of doing so.
If the selective importing is not an option, and you are still keen on making an inverse of the user selection. One option would be to create 2 ranges (one being the user selected Ranges and the second being the entire sheet), you could perform an intersect check between the two ranges and delete the range if there is no intersection present (ie. delete any cell that is not part of the users selection). This method is provided by the first link I supplied and is quite straight forward.

How to select column and display its current format using VBA Macro?

Please find my requirement below for which I am unable to find any solution:
1. Iterate over workSheet from workbook
2. Find all the columns containing date values using current format/type of column (Here is a trick. Worksheet is not static, it can contain any number of columns containing date values. Columns containing date values may have any name. And such worksheets can be more than one in number)
3. Apply macro on date columns for date formatting (below macro) if "Flag" value is "y"
<code>
Sub FormatDate()
If wksSecDist.Range("Flag").value = "y" Then
LastRowColA = Range("X" & Rows.Count).End(xlUp).Row
' Here I am finding total number of rows in column X
wksSecDist.Range("X2", "X" & LastRowColA).NumberFormat = "dd/mmm/yyyy"
' Here applying specified date format to Range("X2", "X10") [if last row index for column X is 10]
End If
End Sub
</code>
I am just a beginner to VBA.
Thanks in advance.
I suspect you didn't find a solution on the internet because you looked simply for a solution and not the parts needed to build your own solution.
You mention you are a VBA beginner, please take the below answer to be of educational use and begin you in getting you where you need your tool to be. Note, if it doesn't answer your question because of information that was not included, it has still answered your question and the missing information should form part of a new question. That said, lets get this function up and running.
From what you have written I have interpreted the requirement to be: -
Look over all worksheets in a workbook ('worksheets can be more than one in number')
Check every column to see if it holds a date value
If it does, set the whole column to a specific format
What is needed to accomplish this is iteration(loops), one to loop through all worksheet, and another to loop through all columns: -
The is pseudo code of the target: -
.For each Worksheet in the Workbook
..For each Column in the Worksheet
...If the Column contains dates then format it as required
..Process next column
.Process next Worksheet
We achieve this using a variable to reference a Worksheet and using a loop (For Each) to change the reference. The same goes for the columns.
Public Sub Sample()
Dim WkSht As Excel.Worksheet
Dim LngCols As Long
Dim LngCol As Long
'This loop will process the code inside it against every worksheet in this Workbook
For Each WkSht In ThisWorkbook.Worksheets
'Go to the top right of the worksheet and then come in, this finds the last used column
LngCols = WkSht.Range(WkSht.Cells(1, WkSht.Columns.Count).Address).End(xlToLeft).Column
'This loop will process the code inside it against every column in the worksheet
For LngCol = 1 To LngCols
'If the first cell contains a date then we should format the column
If IsDate(WkSht.Cells(2, LngCol)) Then
'Set right to the bottom of the sheet
WkSht.Range(WkSht.Cells(2, LngCol), WkSht.Cells(WkSht.Rows.Count, LngCol)).NumberFormat = "dd/mmm/yyyy"
End If
Next
Next
End Sub
Hopefully that has all made sense, this does work on the premise that the header row is always row 1 and there are no gaps in the columns, but these are separate issues you can approach when you're ready to.

Using a Lookup at Next Available Line in Excel VBA

I am trying to implement a lookup feature in Excel Vba. I do not have any code to share because I am uncertain how to begin with the implementation.
Upon opening a workbook I want to use VBA to enter today's date into the next available row in column A - which I currently have working now. However, at that point in Column B on that same line, I to find a stock rate in a table I have, where J2 is the date and J3 is the price of the stock.
What I think I need is a formula where I can lookup the date I just added in this table and then retrieve the price relevant to that date. I understand Vlookups in Excel very well; it is I just do understand how to use a lookup here for each next available line.
Here is my code for the dates:
Dim rnum as integer
rnum = sheet17.usedrange.cells.rows.count +1
sheet17.cells(rnum, 1).value = date
I am seeking lookup functionality relative to (rnum, 2) as the next available line.
If you want to hardcode it, that'd be
sheet17.cells(rnum, 2).formula = "=vlookup(" & sheet17.cells(rnum, 1).address(false,false,xlA1) & ", $J:$K, 2, false)"
If you would prefer to use whatever formula is on the previous line,
sheet17.range(sheet17.cells(rnum-1, 2), sheet17.cells(rnum, 2)).FillDown
I'm assuming when you say "stock rate in a table" you mean "stock rate in a worksheet" and also assume that the values in column J contain the stock rates for the same stock. In other words, you are only matching on a date in that column and not the stock symbol AND the date. (Please let me know if I have these assumptions wrong).
That being, said you can try the following formula in column B:
=IF(A50<>"",INDEX(J:J,MATCH(A50,StockSheet!J:J,0) +1),"")
In this case, the formula is in cell B50 and assumes the new date is in A50. It says given the date value in cell J + n, give me the value in cell J + n + 1.
I added a small validation check to see if there was a value in A50, but you may want to go deeper than that.
Also, if you want to make the value in B50 static, then just use the following code:
Sub mySub()
Dim x As Range 'I assume this range will be for your currentm, working worksheet
Set x = Range("B50", "B50")
x.Formula = "=IF(A50<>"""",INDEX(J:J,MATCH(A50,Codes!J:J,0) +1),"""")"
x = x.Value
End Sub