Tabulating a final score for a questionnaire - vba

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

Related

Fill a table with input from other table via VBA

I am trying to fill a table in one sheet with input from another table (different sheet "wsQuant") based on this function:
=CountIfs(Tabelle14[Question1];[#[Q1]];Tabelle14[Name];[#[Name]];Tabelle14[Participation];[#[Participation]])
This works, but since the table is very big, I am trying to realize it via VBA since the file always crashes (I assume it's too much calculation at once). My solution so far is:
Sub DataBase()
Dim wsQuant As Worksheet
Set wsQuant = Worksheets("quantitativ")
Range("I5").Value = WorksheetFunction.CountIfs("wsQuant[$Z$4:$Z$1000]", [#[Q1]], "wsQuant[Name]", [#[Name]], "wsQuant[Participation]", [#[Participation]])
End Sub
This doesn't work and I can't figure out why.
I searched the entire day now and didn't find any answers.
Any help would be gratly appreciated.
EDIT:
Sample:
Data from the questionaire
This is how the data is given. Answers to the questions on a scale from 1 to 5.
List to be filled
This list should be filled through counting the answers that match the first 4 cloumns.

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

Newbie to VBA, Need a tricky function

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)

Copy cells if specific text is found

I seem to have a problem and currently have not found a solution to it, which is why I address this question to you:
Each day I have a list of invoices and orders coming from different suppliers, and the orders are based on part numbers and types.
This list is imported as text and then goes through a macro I made, to arrange everything in cells.
I also need to go through some steps to format this list based on the type of order (ex: windshield, carpets, wheels, etc ). what I usually do is to filter everything and select the order type that I am interested, and then copy on the same row cells with text and formulas from another worksheet, named "template", which is a list of conditions .
Since it varies from day to day, it may not necessarily contain all part types, which is I couldn't use a macro, and I have to continue by hand, and sometimes the list exceeds 200-300 lines.
To give you an example, if E2 has "windshield" I copy in M2 to Q2 a selection of cells from "Template" (M2 to Q2), if "carpets" I copy M3 to Q3, and so on. the list of conditions is around 15 - 20 rows, and sometimes 2 conditions may apply (if order exceeds $5000 I mark it red, if overdue I bold everything, etc) but mainly I copy based on text in coll E.
If this could be copied into a macro, I would really appreciate it, as I need to take some steps every time, like auto-fit, copy header, format the amounts as number (from text), change text color based on order type, etc, and this too takes time.
I hope this information is enough to make an idea about this, and if not, I could post an example of the list I have to work with.
Many thanks in advance for your support
Use Application.Worksheetfunction.Match to find in which row in Template the to-be-copied cells can be found, then copy range M-Q for this row and paste in your file
You are asking too much in one question to get help here. We are best at single issue questions. The text and code below is intended you give you some ideas. If your code does not work, post the relevant part here and explain the difference between what it does and what you want it to do.
The problems you mention do not sound difficult. I would expect basic VBA to be enough to get you started. Are you looking for bits of relevant code without learning VBA. If you are, this is a big mistake. Search the web for "Excel VBA tutorial" or visit a large library and review their Excel VBA Primers. There are many tutorials and books to choose from so select one that is right for you. The time spent learning the basics will quickly repay itself.
Dim RowCrnt As Long
Dim RowLast As Long
With Worksheets("xxxx")
RowLast = .Cells(Rows.Count,"E").End(xlUp).Row
For RowCrnt = 2 to RowLast
' Code to process each row goes here
Next
End With
The above is probably the structure of your code. The For loop will examine each row in turn which will allow you to take relevant actions.
I have used "E" as a column letter because your question suggests column "E" is the most important. However, code that references columns in this way can be very confusing. Worse, if the column positions change, you will have to work carefully through your code changing the column letters. Better to have some statements at the top like this:
Const ColDate As String = "A"
Const ColAmtInv As string = "B"
Const ColAmtPaid As string = "C"
Const ColProdType As String = "E"
With these constants every reference to a column uses a name not a letter. The code is easier to read and, if a column moves, one change to the constant statement will fix the problem.
The Select Case statement is useful:
Select Case .Cells(RowCrnt, ColProdType).Value
Case "carpets"
' code for carpets
Case "windshield"
' code for carpets
Case Else
' Unknown product type
.Cells(RowCrnt, ColProdType).Font.Color = RGB(255, 0, 0)
End Select
You can have a string of If statements so multiple actions can occur on a single row:
If DateAdd("m", 1, .Cells(RowCrnt,ColDate).Value) < Now() And _
.Cells(RowCrnt,ColAmtInv).Value) > .Cells(RowCrnt,ColAmtPaid).Value Then
' Invoice overdue
.Rows(RowCrnt).Font.Bold = True
End If
If .Cells(RowCrnt,ColAmtInv).Value) > 5000 Then
' Large invoice
.Rows(RowCrnt).Font.Color = RGB(255, 0, 0)
End If
You do not have to write the entire macro in one go. If most action is because of the product type then try that first.
Hope this helps get you started.

External Data Pull: Pull more specific data or change macro based on data

This question is somewhat difficult to explain, so bear with me.
I am pulling data from a large table for my company and am trying to create a macro to make this data easier to read/understand. The data that is on the site changes every day based on what caused certain failures in our plant, which causes my macro to analyze data that isn't there or wrong cells (due to rows getting shifted/moved/added/removed). Because I don't think that was really clear, here is an example:
The macro says to select cells J5, J13, and J25. These were, when I was creating the macro, the values I wanted to be put in a list. However, when I pulled the data and ran the macro today, these values were in different spots on my sheet (the value for cell J13 is now in J12). This completely messes up all of the analysis and renders my macro / data pull useless.
Is there a way to have the macro select the data more intelligently? Perhaps have it check for the group name, then select the value from the cell next to it? I wish I could word this better... Thanks if you've gotten this far!
Simply put... yes. Here's a code exert for looking for a groupname and getting the adjacent cell:
Dim Group1Range As Range
'Look in ThisWorkbook
With ThisWorkbook
'Look in Sheet1
With .Sheets(1)
'Look in Column I
With .Columns("I:I")
'Find the text Group1
Set Group1Range = .Find(What:="Group1").Offset(0, 1)
End With
End With
End With
'Indicate the address of the found range
Debug.Print Group1Range.Address
End Sub
Now here are ways that you can improve your question:
Explain how you know that cell J13 is no longer valid, and that J12 is now.
Give us some sample data.
Give us your code.
Tell us what your end result would be, possibly with an example.