Newbie to VBA, Need a tricky function - vba

Thanks in advance for any help...
(This is for a military unit to help keep track of which Service Members need to do which trainings.)
I need to take a bunch of data (on different sheets, all exported from the same location and formatted exactly the same) and copy them into one master sheet, but with the data inverted...
I have a bunch of sheets (like 25) with a list of names (and other administrative data) that shows who has completed a specific training, each sheet being for a different training. Instead of deficiencies by training, I'd like to have deficiencies by name.
The exported data is always formatted like so:
Title of Training
Last 4 Last Name First Name Rank Unit MOS Skill Level Most Recent
xxxx Last First RNK Unit MOS SkillLevel Date
I'd like a Master Sheet that looks like this:
Training Deficiencies
Last 4 Last Name First Name Rank Unit MOS TitleA TitleB etc
xxxx Last First RNK Unit MOS x x x
xxxx Last First RNK Unit MOS x
xxxx Last First RNK Unit MOS x x
Skill Level and Most Recent will be different for each training, and are irrelevant for the master sheet. The Titles (TitleA, TitleB, etc) can each be copied from Cell(1,1) of the respective sheet, and is also the title of the sheet itself.
I created a sheet with everyone in the unit, so my first step is to create the master sheet (I just delete the whole sheet and create it again):
Sheets("MasterSheet").Delete
Sheets("DataSheet").Copy After:=Sheets("DataSheet")
ActiveSheet.Name = "MasterSheet"
Cells(1, 1).Value = "'Master Sheet"
What I can't figure out how to do is loop through the Last4 on the Master Sheet and compare them against the Last4 in each training sheet.
So for each training sheet:
I want to create a new column on the MasterSheet with the training title as the column heading
Loop through each name on the training sheet and find that Service Member's row.
Put an "X" in the respective training column for that Service Member.
After that, I'd like each Service Member to be highlighted Green, Yellow, or Red based on the number of X's in their row. I think once I get the data copied I'll be able to figure out the highlighting and other formatting.
Thanks again for your help. I can't begin to express how much time this will save (it's currently done by hand). I've been on Google all day and I can find snippets of stuff but I don't really know how to put it all together. I'm using Excel 2007. I have an IT background and understand some code, but it's been a very very long time since I've done some real coding, and VBA is really confusing me.
Thanks again for your help in advance!

I would do like this
create a scripting.dictionary
add all last4 from all sheets to the dictionary
loop the dictionary and output all keys on the master sheet and set the value for each key to the row number
loop all sheets again and look up the row number in the dictionary and set cell to 1
create a formula to sum per row and use conditional formatting for colors
(And use cell format "'x';;' if "x" is a hard requirement)

Related

Copy relevant rows and paste to new worksheet

I have multiple sheets which I am looking to copy and paste the relevant cells from rows into a new worksheet. The defining factor is whether the rows are "Live" which is determined by whether today falls between the "start date" and "end date" columns. For all rows that are "live" certain cells on that row should then be copy pasted to the bottom of the list on the new worksheet. I would then repeat these steps for the other worksheets so that the new worksheet essentially contains a summary of all "live" lines from the other sheets.
I then ultimately need to create a button so I can re-run this at the end of each day.
Hoping you can help!
You've defined and explained what you want to do nicely. So the next step would be to start researching the actions you want the code to do:
Start with how to copy rows:
http://www.bluepecantraining.com/copying-moving-rows-columns-excel-vba/
Next is how to find the last used row in a worksheet:
https://powerspreadsheets.com/excel-vba-last-row/
Next is to apply your condition on what rows to copy:
Using VBA to check if a date is between two dates
Next is how to create a for loop that runs the code the desired number of times:
https://www.excel-easy.com/vba/loop.html (a tip is to use the LastRow that you defined via the second link i posted. eg: "For x = 1 To LastRow")
And lastly is how to assign a macro to a button or shape:
https://wellsr.com/vba/2017/excel/how-to-assign-a-macro-to-a-shape-in-excel/
Try to build a code with the help of these links. If you get stuck, come back and show us what you've created and where the problem is. I (aswell as and many others) would love to help you on from there.

Vba email generator, subject from excel spreadsheet

I have a vba code that generates an email. I would like the subject to be the data from the first and last cells in my list. The thing is, my list isnt of a set length, sometimes it contains 5 pieces of data sometimes 8 etc. How do i tell vba to pick the first and last cell no matter the length of the list?
thanks
For me, best practice is to just have cells on your sheet that calculate the first and last row (different ways you can do that), then give those cells a range name such as FirstRow and LastRow. In your vba then you refer to these cells to make your code dynamic.
e.g:
firstRow = Range("FirstRow)
lastRow = Range("lastRow")
test = range(cells(firstRow,lastRow))
-- Note I have not written VBA in many many years so am writing the above from memory so it may be not be exact.
Of course you can do it all entirely in VBA using the xlDown method mentioned previously but I prefer the transparency of it being on the main page so that easily spot if something breaks.
Range("A1").End(xlDown).Value
Where the cell is where you want to start and the End part moves all the way to the end

Search xlsx for a value, if found replace with different value

So I'm either being too specific, or not searching well enough, because I can't find anything that answers my question. So I came here for help. Here is the situation:
I have an excel sheet, let's call it "CustomerCodeReference", that has a column (A) of Customer Codes (I.E. A2001, A2002, B3900, Q2838, etc, these are NOT necessarily in order) About 3000 of them, and in the next column over (B), I have the group that code represents (I.E. Accounts Primary, Accounts Secondary, Admin Group, User Group, just different names and etc.)
Now, from our company server I can export a spreadsheet of reports from customers, but the problem is, they are labelled by customer code, + a report serial number. The sheet exports as several columns, but one of the columns (G) contains the Customer code and serial number, and each row is a report, sometimes hundreds depending on the date range set. So keeping with the example, let's say it's a report from "Accounts Primary" It's labelled A2001234567 (where everything after the customer code of 'A2001' is the report serial number) sometimes, the report may be from several customers, so that column may have more than one code+SN in it per row.
Given that I have thousands of these codes and groups, is there some macro I can create that every time I export the spreadsheet of reports, I can maybe copy over the "CustomerCodeReference" sheet, and have it automatically search the column of customer codes and SNs, then either replace the code with the actual name, or place the actual name in another (empty) row further back. So I can basically easily reference whose report it is without having to look up the code each time?
I realize I will need to do this in VBA, as there is no formula I can think of that will work.
I have some pro's I think going for me:
-I already have the Master code list, so even though there are thousands of codes, they are all listed in Column A, and the actual name of group they reference is in column B.
-The codes are consistent, a letter, followed by 4 numbers, so always 5 characters long.
-When pulling the report, it always names the worksheet "Customer Reports" so it's easy to reference
These are constants. So I need the actual customer name to either replace the code (while leaving the serial number intact) or if easier, add the actual name to the next empty column on the same row. I also might need to share this with coworkers, so basically just send them the "CustomerCodeReference" sheet and when they add it to all their pulled spreadsheets, it does the same thing. (Macros will be enabled, so no worries there)
Is this too complicated an idea? or can I pull it off? Thanks in advance for the help!
EDIT: I apologize, I complete forgot to attach any sort of code. Here is what I have come up with in VBA, but not sure if I am on the right track as it does not complete the replacement, and I can't quite get it to add values in next available empty cell.
Sub replaceStringInCell()
'declaring my sheet I want to change change customer codes in
Dim CustomerCodes As Range
'declaring strings I will be replacing and with what I will be replacing them
Dim ReportNumbers As Range
Dim CustomerNames As Range
'identifying column I am working to replace, also trying to shoot for next empty column
Set CustomerCodes = PulledReports.Worksheets("Customer Reports").Range("G:G")
'specifying my strings
ReportNumbers = PulledReports.Worksheets("Customer Reports").Range("G:G")
myReplacementString = PulledReports.Worksheets("Customer Code Reference").Range("A:A")
'replace string in cell
CustomerCodes.Value = Replace(Expression:=CustomerCodes.Value, Find:=ReportNumbers, Replace:=CustomerNames)
End Sub
This should do the trick:
Sub stack_overflow()
Dim cust As Worksheet
Dim ref As Worksheet
Set cust = ActiveWorkbook.Worksheets("Customer Reports")
Set ref = ActiveWorkbook.Worksheets("Customer Code Reference")
'Finding next empty column
Dim column As Integer
column = cust.UsedRange.Columns.column + 1
'Filling this columns
For Each cell In cust.Range("G2:G" & cust.Cells(Rows.Count, "G").End(xlUp).Row)
cust.Cells(cell.Row, column).Value = Application.WorksheetFunction.VLookup(Left(cell.Value, 5), _
ref.Range("A2:B" & ref.Cells(Rows.Count, "B").End(xlUp).Row), 2, False)
Next cell
End Sub

Tabulating a final score for a questionnaire

Thanking in advance for your help with this one. I have searched everywhere but haven't been able to find an answer that addresses my issue.
Here is the background:
I have a questionnaire with 15 questions for which the possible answers are “Y”, “N” or “N/A”. For each question, I have assigned to the “Y” a value and to the “N” and “N/A” a zero.
I need a macro that will, for the active row in question, identify the heading of each question (1-15), look up each heading on a different worksheet in the same file, locate the number assigned to it if the answer is either “Y” or “N” (ignore the “N/A”s) and add all those numbers for the base score.
Then, as a second step, the macro will add only the “Y” answers and tabulate them against the base score for a final score.
For illustration purposes let’s say that I have the following questions:
Table Chair Lamp Plant
Y Y N N/A
In a different tab, the table looks like this:
Table Chair Lamp Plant
5 10 8 15
I need a macro that will look at the column headings to match them, and then at the values assigned to table, chair and lamp (ignore plant since N/A), add them (for a total of 23). Then add only the Ys (for a total of 15) and then produce a final score of 65 (15 out of 23 or 65%).
Really stuck with this one… I have no idea how to even start… any help is truly appreciated.
Thank you so much!!!!
Marta
When you have a big task in front of you, you need to divide it up incrementally. Stack Overflow isn't here to write your macro for you.
The first part you want to do is match the column headers in the Active Row with the column headers on another worksheet, right? What I've posted below should get you the column headers on the question sheet and read them off to you. Try it out and take it further (do some googling if you need to). When you run into a problem with the code you make, that's where a question should be asked.
(Place this code into a fresh module in your workbook, and connect it to a button or something on the questionnaire worksheet)
Public Sub TallyQuestions()
Dim questionSht As Worksheet
Set questionSht = Sheets("Worksheet that has the questions you were talking about") 'replace name with name of questionSht
Dim questionShtColHeaders As Range, cell As Range
Set questionShtColHeaders = questionSht.Range("A1:A15")
For Each cell In questionShtColHeaders
MsgBox cell.Value
Next cell
End Sub

How to format/color cells based on contents of other cells

I am trying to automate an Excel workbook to help save time in making employee work schedules. I have two sheets. Sheet1 contains a simple table used to create the intended schedule for the month (employee name in first column, dates on the top row, and every day is marked with "WORKING", "ON CALL", "OFF", etc.), and the other sheet contains a table with color codes to keep track of how well the schedule was actually kept as the weeks pass. I need Sheet2 to update the color codes based on the schedule manually planned on Sheet1 so I can waste less company time manually color coding cells.
I don't want to use Conditional Formatting, since I believe you can't overwrite the format it gives a cell (in the case an employee called out rather than coming in on his scheduled day to work and on Sheet2 this needs to be recorded - with a different color code). I just need help figuring out some macro that can help speed things up and waste less company time manually color coding cells.
I don't want to record a macro this time, since names and days working can/will be different every time the schedule is updated/made.
Here is something you can work on.
Right click on the sheet 1 tab and select "View Code" copy and paste this code there.
Change a cell in Column A in sheet 1 to A,B or C then go to sheet 2 and see what happened.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 1 Then
If Target = "A" Then Sheets("Sheet2").Range(Target.Address).Interior.ColorIndex = 3
If Target = "B" Then Sheets("Sheet2").Range(Target.Address).Interior.ColorIndex = 4
If Target = "C" Then Sheets("Sheet2").Range(Target.Address).Interior.ColorIndex = 5
End If
End Sub