So, I haven't figured out how to do this.
Basically, I want something like this:
P1 P2 P3 TOTAL SCORE
-- -- -- P1 P2 P3
21 / 13 1 2 0
/ 17 10
6 7 /
So, the three columns must compare to one-another (the "/" means that the player didn't play that game, but it doesn't have to be printed), the greatest among the three gets a +1 value in the TOTAL SCORE tab.
Plus, is there any easier way to do this than comparing one cell to another cell? I mean, is there a possibility to drag and mark all cells on all of the three columns and make sure that they only compare the cells in the three columns IN THE SAME ROW?
Let us assume that the data appears as in the picture in Sheet1 (Don't change the structure):
Open an Excel
Press ALT & F11 to open Visual Editor
Add a module from > Insert (in the Upper toolbar) - Module ( third option)
Paste the below codes & execute Sub Evaluation() (press F5 when your cursor is in Sub Evaluation)
To store lastrow in order to continue from the next record i use sheet2 range A1
Try:
Option Explicit
Public Sub Process_Data(ByVal I_Value As Long)
Dim LastRow As Long
Dim i As Long
Dim CA As Integer
Dim CB As Integer
Dim CC As Integer
With Sheet1
LastRow = .Range("A" & Rows.Count).End(xlUp).Row
For i = I_Value To LastRow '<= Lets say that the first score is at sheet1 column A row 3.LastRow represent the row of the last data in column A
CA = 0
CB = 0 '<= Every time that i change value we zero our variables to get the new value
CC = 0
If .Range("A" & i).Value = "/" Then '<= Check if there is a number or "/".if there is "/" we zero variable
CA = 0
Else
CA = .Range("A" & i).Value
End If
If .Range("B" & i).Value = "/" Then
CB = 0
Else
CB = .Range("B" & i).Value
End If
If .Range("C" & i).Value = "/" Then
CC = 0
Else
CC = .Range("C" & i).Value
End If
If CA > CB And CA > CC Then ' <= Check which number is bigger
.Range("E3").Value = .Range("E3").Value + 1 '<= At one point to each category
ElseIf CB > CA And CB > CC Then
.Range("F3").Value = .Range("F3").Value + 1
ElseIf CC > CA And CC > CB Then
.Range("G3").Value = .Range("G3").Value + 1
End If
Next i
End With
End Sub
Sub Evaluation()
Dim Value As Long
Dim LastRow As Long
LastRow = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
If (LastRow = 2) Or (LastRow = Sheet2.Range("A1").Value) Then '<= Check if the table has new data
Exit Sub
Else
If Sheet2.Range("A1").Value = "" Then '<=Check which value will adopt be i
Value = 3
Else
Value = Sheet2.Range("A1").Value + 1
End If
End If
Call Process_Data(I_Value:=Value)
Sheet2.Range("A1").Value = Sheet1.Range("A" & Rows.Count).End(xlUp).Row '<= Record the lastrow processed out
End Sub
Use the LARGE function to find the highest number for the individual games on the left. Then use an IF statement out to the right to check if the value of the LARGE function matches the player's game score. If it does match (TRUE), assign a value of 1. If it doesn't match (FALSE), assign a value of 0. Then SUM each player's modifiers that you've assigned with the IF function.
If ties are possible in the individual game scores, you'll also need to nest another IF function to handle that possibility.
Related
thank you for the help in advance!
I am creating a macro that writes to a text file. I am having trouble referencing a range inside of a for loop. There are two examples I have where the range I have called returns a "". For the first image below, this is where the user inputs data using a combination of entering data into the sheet and using a button that directs them to a user form that plops in what they entered. In this first image, where the user is directed by the userform, the data is outputted to another sheet and I use vlookup to display the info. I do this to run operations on the other sheet and just to help me keep track of everything, (novice vba user). The second sheet is where data is stored and calculations are run.
1st image, User input and display 2nd image, data storage and calculation sheet
newDimName only outputs "_Cav" and the value stored in cavNum for the loop. The intention is concatenate the string inside of column A with more information depending on what the user has inputted. I suspect I am not referencing the range for column a correctly. The Loop is set to go to 2 to whatever amount of "dimensions" have been entered by the user (value in lastUserDim). The code below is contained with a sheet reference (not in the snippet) so it references the correct sheet. Ex. "With Sheet2", at before the loop and a "End With" at the end of the loop.
Dim a As Integer, cavNum As Integer
Select Case numCav
Case Is = 4
For a = 2 To lastUserDim
For cavNum = 1 To 4
newDimName = Cells(a, 1) & "_Cav" & cavNum
Next cavNum
Next a
totalColumns = 4 * lastUserDim
Case Is = 8
For a = 2 To lastUserDim
For cavNum = 1 To 8
newDimName = Cells(a, 1) & "_Cav" & cavNum
Next cavNum
Next a
totalColumns = 8 * lastUserDim
Case Is = 16
For a = 2 To lastUserDim
For cavNum = 1 To 16
newDimName = Cells(a, 1) & "_Cav" & cavNum
Next cavNum
Next a
totalColumns = 16 * lastUserDim
Case Is = 32
For a = 2 To lastUserDim
For cavNum = 1 To 32
newDimName = Cells(a, 1) & "_Cav" & cavNum
Next cavNum
Next a
totalColumns = 32 * lastUserDim
Case Else
MsgBox "Please select what # of cavities this tool has."
End Select
For the code below, I want the the range I defined to be read and for the select case to determine if a cell contains yes or no. The loop is intended to run this operation for number of user inputted data. Again I suspect I am not calling the data in column c correctly like I was previously with Column A. I tried using cells like in the first code snippet, just range, range("").value, and range("").text.
Dim LSLBound As String, LSLBoundRef As String
Dim c As Integer
For c = 2 To lastUserDim
LSLBoundRef = Range("C2:C" & c).Text 'ref to cell value to use for select case
Select Case LSLBoundRef
Case Is = "No"
LSLBound = "LBound 1;"
Case Is = "Yes"
'Do Nothing
End Select
Next c
If the second code snippet is wrapped in a "With Sheet2", you need to preface the Range with a period, ie **.**Range("C2")... so that it is using the correct sheet.
Dim LSLBound As String, LSLBoundRef As String
Dim c As Integer
With Sheets("Sheet2")
For c = 2 To lastUserDim
LSLBoundRef = .Range("C2:C" & c).Text 'ref to cell value to use for select case
Select Case LSLBoundRef
Case Is = "No"
LSLBound = "LBound 1;"
Case Is = "Yes"
'Do Nothing
End Select
Next c
End With
A good way to figure out what range is actually being referenced is by printing the range address to the immediate window with Debug.Print Range.Address.
I have a dataset that consists of 5 different variables. As shown below.
Value1 Value 2 Value 3 Value 4 Value 5
1200.08031 104.9940186 28.05707932 23.90201187 1198.955811
1200.01948 105.0005951 28.05075455 23.88057899 1198.984619
1199.9152 105.0007782 28.04256058 23.86779976 1199.18042
1199.90651 105.0114594 28.05139923 23.90410423 1199.148926
1200.01079 104.9975433 28.05404663 23.89129448 1198.660034
1199.97603 104.9940186 28.0475502 23.91586685 1198.932129
1199.89782 105.0007782 28.04875183 23.87851715 1198.928833
1200.01948 105.0056458 28.04198837 23.91583633 1199.087524
1199.87175 105.0026855 28.04278946 23.91485214 1198.896851
1199.97603 105.0054626 28.04265976 23.9235096 1199.426514
Each of these variables has around 15,000 data points. To reduce the number of data points I want to average every ten data points into one data point and assign this value to a cell on another sheet. I want it to look like:
Value1Avg Value 2Avg Value 3Avg Value 4Avg Value 5Avg
1200.08031 104.9940186 28.05707932 23.90201187 1198.955811
I cannot get the average function to loop through every ten data points.
I have tried to run a loop that goes through each column and averages the values and places them on a different sheet, but I am not incrementing the variables correctly I believe.
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("RawData")
Set sht2 = wb.Sheets("FilteredData")
ii = 2
j = 11
dd = 2
k = 20
n = 1
LastRow = sht1.Range("A:A").Find("*", searchdirection:=xlPrevious).Row
For i = 1 To LastRow
Set Myrange = sht1.Range("E" & ii, "E" & j)
sht2.Range("A" & n).Value =Application.WorksheetFunction.Average(Myrange)
Set Myrange = sht1.Range("B" & ii, "B" & j)
sht2.Range("B" & n).Value = Application.WorksheetFunction.Average(Myrange)
Set Myrange = sht1.Range("C" & ii, "C" & j)
sht2.Range("C" & n).Value = Application.WorksheetFunction.Average(Myrange)
Set Myrange = sht1.Range("H" & ii, "H" & j)
sht2.Range("E" & n).Value = Application.WorksheetFunction.Average(Myrange)
Set Myrange = sht1.Range("D" & ii, "D" & j)
sht2.Range("D" & n).Value = Application.WorksheetFunction.Average(Myrange)
ii = ii + 10
j = j + 10
n = n + 1
Next i
I expect to go to sheet 2 and see the averages, but I get:
"Run-time error '1004': Method 'Range' of object '_Worksheet' failed"
Here is a potential alternative that may be a little easier to follow by making use of nested loops. This way you do not have to complete the average for each column one by one, instead you can just have your action line written once situated inside a row & column loop.
Simplifying variables will also make this easier to update / debug in the future.
Sub Jeeped()
Dim rd As Worksheet: Set rd = ThisWorkbook.Sheets("RawData")
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("FilteredData")
Dim LR As Long
LR = rd.Range("A" & rd.Rows.Count).End(xlUp).Row
Dim c As Long 'Column Loop
Dim r As Long 'Row Loop
Dim x As Long 'Paste counter
x = 2
Dim TempAverage As Range
For r = 2 To LR Step 10
For i = 1 To 5 '<-- (Columns A - D)
Set TempAverage = rd.Range(rd.Cells(r, i), rd.Cells(r + 9, i))
ws.Cells(x, i).Value = Application.WorksheetFunction.Average(TempAverage)
Next i
x = x + 1
Next r
End Sub
assumes your variables span Columns A:D on RawData and that the values will be pasted on FilterdData on Columns A:D as well. You can modify the loops to place them in the correct location
https://i.stack.imgur.com/RKcpe.png
I have 5 columns that are updated based on the inputs from 5 different users i,e all values that User 1 inputs in his userform are updated in Column 1
all values that User 2 inputs in his userform are updated in Column 2 and so on.However , when this happens there is a possibility that 2 or more users might enter the same value.I want to loop through all the 5 columns and keep only the values that do not repeat in any of the column.
Eg: Please check the image(Question.jpg) for reference
In the image a lot of values are repeated in columns of user 2 , user 3 , user 4 and user 5.
I want to delete the repeated values and keep only the unique values in the respective ranges.
Please watch the 2nd image(Solution.jpg) on how the output should look like.
I tried the code given below but it works only for 1 column and i cannot figure out a way to make it work for all 5 columns.Also , is there a better way to do so?
lastrow1 = wsh.Range("I" & Rows.Count).End(xlUp).Row
For i = 6 To lastrow1
id = wsh.Range("I" & i).Value
lastrow2 = wsh.Range("I" & Rows.Count).End(xlUp).Row
For j = 6 To lastrow2
id2 = wsh.Range("J" & j).Value
If id = id2 Then
wsh.Range("J" & j).Value = ""
Else
wsh.Range("J" & j).Value = wsh.Range("J" & j).Value
End If
Next j
Next i
This will work:
Note:
Make sure to add the Reference Microsoft Scripting Runtime. Tools > References
Change the Range in the Code as Per your Sheet And Range
Code:
Dim dict As New Scripting.Dictionary
Dim i As Integer
Dim j As Integer
Dim val_removed as String
With ActiveSheet.Range("D1:F9") 'Change the Range
For i = 1 To .Columns.Count
For j = 1 To .Rows.Count
If Not dict.Exists(.Cells(j, i).Text) Then
dict.Add .Cells(j, i).Text, .Cells(j, i)
Else
val_removed = val_removed & "," & .Cells(j, i).Value
.Cells(j, i).Value = ""
End If
Next
Next
Set dict = Nothing
End With
Msgbox val_Removed
Scripting.Dictionary is my favorite to Remove Duplicates.
Demo:
Can you guys help me out? I think i'm kind of stuck with the code below. I almost got the code that I wanted but at the end it does not do the thing I like.
Dim acs, cos, as_col, as_row As Integer
cos = Sheets.Count
acs = ActiveSheet.Index
as_LRow = Sheets(acs).Cells(Sheets(acs).Rows.Count, "A").End(xlUp).Row
For as_row = 3 To as_LRow
std_number = Sheets(acs).Cells(as_row, 1).Value
earliersheets = acs - 1
For s = 1 To earliersheets
ilast_row = Sheets(s).Cells(Sheets(s).Rows.Count, "A").End(xlUp).Row
For r = 3 To ilast_row
std_number_new = Sheets(s).Cells(r, 1).Value
If std_number = std_number_new Then
a = a & Sheets(s).Cells(r, 6).Value
'Sheets(acs).Cells(as_row, 8).Value = Sheets(s).Cells(r, 8).Value
Sheets(acs).Cells(as_row, 8).Value = Sheets(acs).Cells(as_row, 6).Value & " + " & a
End If
a = ""
Next r
Next s
Next as_row
What I want is:
After adding, manually, a new sheet I want to press on a button. This button activates the code above. What I want is to check a value in a particulaire cell in column "A". If the value in this column matches with the value from previous sheet then display the value in the sixth column in the newly added sheet. The code above does that, but it works only for two sheets. If I make more then two sheets it does not display more values then two.
Update
I added my file in the link: Check.xlsm
After opening this file clear the H-column in the third (and maybe the second sheet) then run the macro within. You'll see what I mean
All I want is to get all the previous values in previous sheet displaced in column-H. For example I marked two cells with values, these values get displayed in the H-column after running the macro.
Your problem was that you were always storing in column H a value created by taking the value from column F of the current sheet and appending the value from column F of the sheet being processed within the loop. When you move to the next sheet within the loop, you're replacing the previous value with a new value.
So, when processing sheet w3-6, you first look at sheet w1-4 and generate a value of "13 + 34" and store that in sheet w3-6's cell H3. Then you look at sheet w2-5 and generate a value of "13 + 18" and replace the value of "13 + 34" currently in sheet w3-6's cell H3 with the value of "13 + 18".
Try this code instead:
Dim acs As Long, cos As Long, as_col As Long, as_row As Long
Dim s As Long
Dim as_LRow As Long
Dim ilast_row As Long
Dim r As Long
Dim a As String
cos = Sheets.Count
acs = ActiveSheet.Index
as_LRow = Sheets(acs).Cells(Sheets(acs).Rows.Count, "A").End(xlUp).Row
For as_row = 3 To as_LRow
std_number = Sheets(acs).Cells(as_row, 1).Value
'Initialise variable containing result to go into column H
a = Sheets(acs).Cells(as_row, 6).Value
'Process earlier sheets in reverse order
'(so that values will be shown in reverse order)
For s = acs - 1 To 1 Step -1
ilast_row = Sheets(s).Cells(Sheets(s).Rows.Count, "A").End(xlUp).Row
For r = 3 To ilast_row
std_number_new = Sheets(s).Cells(r, 1).Value
If std_number = std_number_new Then
'Append value to result string
a = a & " + " & Cstr(Sheets(s).Cells(r, 6).Value)
Exit For
End If
Next r
Next s
'Store result
Sheets(acs).Cells(as_row, 8).Value = a
Next as_row
lets say in column A:Row 2, I have a score of 45 and in column B, I have the amount of people that got that score. what i then want to do is on column D, output that score X amount of times. x=repitition.
in the exmaple 5 people got a score of 45 so in column D i want to insert 5 scores of 45. then I see in column A:Row2 3 people got a score of 46 then after the last 45, in column D I want to append 46 3 times.. and so on..
Could someone show me how to do this?
Here you go:
Sub test_scores_repitition()
'run with test scores sheet active
r = 1
dest_r = 1
Do While Not IsEmpty(Range("a" & r))
If IsEmpty(Range("b" & r)) Then Range("b" & r).Value = 0 'if there's no quantity listed for a score, it assumes zero
For i = 1 To Range("b" & r).Value
Range("d" & dest_r).Value = Range("a" & r).Value
dest_r = dest_r + 1
Next i
r = r + 1
Loop
End Sub
Macro answer:
Sub WriteIt()
Dim lrow As Long
Dim WriteRow As Long
Dim EachCount As Long
Dim ReadRow As Long
' find last in list of numbers
lrow = Range("A1").End(xlDown).Row
'start at 2 because of headers
WriteRow = 2
ReadRow = 2
While ReadRow <= lrow
For EachCount = 1 To Cells(ReadRow, 2)
'repeat the number of times in column B
Cells(WriteRow, 4) = Cells(ReadRow, 1)
'the number in column A
WriteRow = WriteRow + 1
Next
ReadRow = ReadRow + 1
'and move to the next row
Wend
'finish when we've written them all
End Sub
it is possible with a formula, just not really recommended as it looks auful, and would be difficult to explain. It uses a Microsoft formula to count the number of unique items in the data above, and once it counts the number it is supposed to write of the number above, it moves to the next number. The formula does not know where to stop, and will put 0 when it runs out of data.
in D2, put =A2
In D3, and copied down, put
=IF(COUNTIF($D$2:D2,OFFSET($A$1,SUM(IF(FREQUENCY($D$2:D2,$D$2:D2)>0,1)),0))<OFFSET($B$1,SUM(IF(FREQUENCY($D$2:D2,$D$2:D2)>0,1)),0),OFFSET($A$1,SUM(IF(FREQUENCY($D$2:D2,$D$2:D2)>0,1)),0),OFFSET($A$1,SUM(IF(FREQUENCY($D$2:D2,$D$2:D2)>0,1))+1,0))