Let Excel Solver Operate with Natural Numbers - excel

My workbook is a bit complicated, but the basic problem can be illustrated with a short example.
Let's assume that I have 5 cells in Excel: A, B, C, D, and E.
A = 0
B = 5 * A
C = 0
D = 10 * C
E = B + D
In the Excel Solver Function I select cell E as the objective that is to be maximised, and cells A and C as the variable cells. Furthermore, I add the constraint that cell E must not exceed 10, and the second constraint that cells A and C must be integers.
The ideal solution would be that the value in cell A should be 0, and the value in cell C should be 10. In the more complicated version of this problem, however, Excel cannot find the optional solution.
The way the current formulas look like I expect that Excel could find the right solution, if excel only used natural numbers to find the optimal solution. For example, Excel currently would look at the outcome for A = 0.01 and C = 9.99. Instead, Excel should strictly compare outcomes for variable choices such as A = 1 and C = 9.
How can I make the Excel solver function operate with natural numbers only?

I suggest you keep your current cells, and create a mirror set beside them. Each mirror cell will equal the rounded version of the original cell. ie: RoundedA will have the formula:
=ROUND(A,0)
Then when you do your data analysis, solve for the rounded version of those cells, with the changing variable being one of the "original" cells.
EDIT
As discussed below, you may need to 'trick' data validation into creating the values you want.
Assume A1 is going to be your "testing" data validation cell. B1 is a permanently blank cell. Set another cell, say, C1, equal to:
=randbetween(1,10)
This will create a random integer between 1 and 10. Set your "variable" cell to be equal to C10. So, your variable cell will always be a random number between 1 & 10 (or you could set "1" equal to the smallest number of your other variables, and "10" equal to the largest number of your other variables. This will create the scope needed to answer your question).
Then when you do data validation, make it try to get A1 = TRUE. Do this by figuring out what the 'test' condition is of your cells. Something like "when X = 0, I know that all my variables are correct". ie set A1 to:
=if(X=0,1,0)
Then do data validation by changing B1 (your blank, unrefered-to cell), waiting until A1 = 1. Does that make sense? It will turn C1 into the random cycling variable between LOWVALUE and HIGHVALUE, always using integers. Data validation will stop when A1 = 1 (which happens when some value X = 0). B1 will just spin uselessly until Data validation finds something (or it will stop after a few hundred tries if it finds nothing).

To get Solver to try larger increment divide the target cells by a large number and in such a way, each increment that solver tries is larger. (for example it changes the target cells by +-0.00001 - in that case divide the target cells by 100000 or more).

Related

Numbering Based on Condition(s)

I'm trying to create auto numbering for Agents that are currently present and has numbers including zeroes 0 in 3rd or 4th column(zero meaning they don't get any stats but they are present)
Agents who has TEXT Value in the 3rd or 4th column are those who are not present (Ex: A = Absent, SL = Sick Leave, VL = Vacation Leave). Meaning, they should not be counted, therefore their value on 1st column should be blank, and therefore this should not stop the auto numbering for the rest of the agents below and should continue the count in sequence.
Can anyone help create formula that would fill the numbers on the 1st column automatically for those agents that are present and has value including 0 on column 3 or 4 (stats 1 or stats 2)?
To give more idea, I'm trying to show the current total number of agents who are currently present in this situation and will count their stats, and exclude all other agents who are not present and should not be counted.
Thank you!
Sequence Two Numeric Columns
Single Cell
In cell A3, a basic not spilling formula would be...
=IF(AND(ISNUMBER(C3),ISNUMBER(D3)),MAX(A$2:A2)+1,"")
... with the condition of a string in cell A2.
Without any conditions, you could try an improved version, similar to one of David Leal's suggestions:
=IF(AND(ISNUMBER(C3),ISNUMBER(D3)),
SUM(ISNUMBER(C$3:C3)*ISNUMBER(D$3:D3)),"")
Spill
In cell A3 you could use the following:
=LET(Data1,C3:C13,Data2,D3:D13,
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,""))
Line1: the inputs ('constants'), the same-sized single-column ranges
Line2: the zeros and ones, where the ones present the data of interest
Line3: the formula to replace the ones with the sequence and the zeros (errors due to division by zero) with an empty string
Converted to a LAMBDA, it could look like the following:
=LAMBDA(Data1,Data2,LET(
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,"")))(C3:C13,D3:D13)
Since it's such a long formula, you could create your own Lambda function by using this part...
=LAMBDA(Data1,Data2,LET(
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,"")))
... to define a name, e.g. SeqNumeric, when in the same cell, you could use
it simply with...
=SeqNumeric(C3:C13,D3:D13)
... instead.
Now you can use the function like any other Excel function anywhere in the workbook.
The Path
F3 =ISNUMBER(C3:C13)*ISNUMBER(D3:D13) - multiply: zeros-no, ones-yes
G3 =SCAN(0,F3#,LAMBDA(a,b,a+b)) - use the 'LAMBDA' helper function 'SCAN'
H3 =G3#/F3# - divide the 'scan' result by the zeros and ones
I3 =IFERROR(H3#,"") - convert the '#DIV/0!' errors to empty strings
The translation of the SCAN part could be something like the following:
Set the initial result a to 0.
Create a new array of the size of the initial array in F3#.
Loop through each element of the initial array, write its value to b, and replace a with the sum of a+b.
Write (the accumulated) a to the current element of the new array and repeat for the remaining elements of either array.
Return the new array.
Combine all of it in a LET.
J3 =LET(Data1,C3:C13,Data2,D3:D13,
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,""))
Convert to LAMBDA.
K3 =LAMBDA(Data1,Data2,LET(
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,"")))(C3:C13,D3:D13)
Copy the first part of the LAMBDA (note how it results in a #CALC! error since no parameters are supplied)...
L3 =LAMBDA(Data1,Data2,LET(
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,"")))
... and select Formulas -> Name Manager -> New to create your own function and finally use it with the following:
A3 =SeqNumeric(C3:C13,D3:D13)
You can try the following in cell A1:
=LET(B, B2:B12, C, C2:C12, f, 1*ISNUMBER(B*C),seq, SEQUENCE(ROWS(B)),
MAP(seq, LAMBDA(s, IF(INDEX(f,s)=0, "",SUM(FILTER(f, (seq<=s),0))))))
Here is the output:
A non-array version, expanding down the formula would be:
=IF(ISNUMBER(B2*C2), SUM(1*ISNUMBER(B$2:B2*C$2:C2)),"")
For the array version, it counts only if both columns Stat1 and Stat2 are numeric. The name f, has a value of 1 if the condition is TRUE, otherwise is 0. The MAP does the count if the index position of the f array is not zero, otherwise returns an empty string.
I think I got it.
This is the formula that I made
=IF(COUNTIFS(D2:BE2,"*",$D$1:$BE$1,TODAY())>0,"",MAX(A1:A$4)+1)
Countif criteria 1 = if the cell contains a letter and is counted > 0 then it will return blank, otherwise it will start the count using max function. The countif criteria 2 will will return the correct value according to the date today since the excel sheet has several data daily.

Excel - Generate Random Number based on 2 other columns

I am not sure how to accomplish the following task:
On columnA I have numbers, on columnB I have names associated to those numbers.
I would like to be able and generate a random number from column A, but only from the numbers that do not have anything associated on column B. For eg.: If I have a number in A1, but I do not have a name in B1, the number from A1 should be one of those that could be randomly generated.
If A2 has a number, and B2 is not empty (it has a name), I do not want to have A2 in the random range.
Also, it would be great to be able and re-generate the random number (aka, If I assign a number, let's say, 321, I want to be able somehow to generate the random number again, but it should not take into consideration 321 as it was already assigned).
I appreciate any ideas.
Sample
You can try the following:
based on your sample data/spreadsheet, do the following:
1) in Cell C1: put the value "0"
2) in Cell C2: put the formula:
=IF(ISBLANK(B2), 1, 0)+OFFSET(C2,-1,0,1,1)
3) copy the formula in C2 down alongside all your data.
4) Put this formula anywhere you want to display the randomized # from Column A:
=OFFSET(A1,MATCH(RANDBETWEEN(1,COUNTA(A:A)-COUNTA(B:B)),C:C,0)-1,0,1,1)
I think you'll have a hard time doing it with worksheet functions. Here's one quick-and-dirty approach that works at least some of the time---
In two (or more) cells, add the formula =RANDBETWEEN(COLUMN(A1),COLUMN(D1)), replacing A1 and D1 with the first and last cells in your row of numbers. This will pick random column numbers.
Give each of those cells a unique name, e.g., therand, therand2, ... .
In another cell, which will be your answer, add =IF(ISBLANK(INDIRECT(ADDRESS(2,therand))),INDIRECT(ADDRESS(1,therand)),INDIRECT(ADDRESS(1,therand2))). This will check whether the first random column number corresponds to a blank label (ISBLANK(...)) and, if so, use the corresponding row-1 value. If not, it will use the row-1 value from the second random column number.
Hit F9 to recalcualate.
This will not always give you a blank-labeled cell. Add more random column numbers and corresponding IF(...) clauses to reduce the probability of a mis-selection.
Edit: you said "row A" in the original question, but I see you meant "column A" (rather than "row 1"). You'll need to transpose the rows and columns in the formulas above to make them work.
Here is a VBA answer. It can be used directly as a worksheet function:
Function RandUnassigned(R As Range) As Variant
Application.Volatile
Dim A As Variant, i As Long, n As Long
Dim num As Long
n = R.Rows.Count
ReDim A(1 To n)
For i = 1 To n
If Len(R.Cells(i, 2)) = 0 Then
num = num + 1
A(num) = R.Cells(i, 1)
End If
Next i
RandUnassigned = A(Application.WorksheetFunction.RandBetween(1, num))
End Function
Used like this:
This recalculates every time the spreadsheet does. If you want it to draw a random number just once, remove the line Application.Volatile from the function definition.

MAX IF function that refers to other sheet

I have a sheet in my workbook called Group Dashboard. On that sheet I am entering a formula referring to another sheet.
=MAX(IF('Worker Dashboard'!C:C=1,'Worker Dashboard'!F:F))
I want it to look through all the data in Worker Dashboard. For each line where the value in the C column is 1 (or 1.0), I want it to consider the value in Column F. It should then output the MAX value among the considered values from Column F.
This formula seems to work fine.
However, when I then enter the following:
=MAX(IF('Worker Dashboard'!C:C="<1",'Worker Dashboard'!F:F))
It just reads 0. The max value should not be 0. Column C in that sheet has values <1 such as 0.8, 0.6, 0.5, etc. If I change the formula to:
=MAX(IF('Worker Dashboard'!C:C="<1",'Worker Dashboard'!F:F,-1))
Then the output is -1. This makes me think there is an issue with the logic statement:
'Worker Dashboard'!C:C="<1"
I have also tried variations for other purposes where the logic statement is:
=MAX(IF('Worker Dashboard'!B:B="General",'Worker Dashboard'!F:F))
However, here too it spits out 0 even though the max is 5.0 for rows where Column B lists General and the value in Row F is considered.
There are two points that I've found from your description of the problem.
Use 'Worker Dashboard'!C:C<1 not 'Worker Dashboard'!C:C="<1". Comparing a true number to the textual representation of that number will work with some functions like the COUNTIF function but not all. Best to compare numbers to numbers and test to text whenever possible.
Your formula looks to be of the array formula variety. Array formulas need to be finalized with Ctrl+Shift+Enter↵ and not just Enter↵. When entered correctly with CSE, Excel will wrap the formula in braces (e.g. { and }). You do not type these in yourself. Once entered correctly, the formula may be copied/filled to new locations with conventional methods like Ctrl+D (aka Fill Down) and the CSE will carry along.

If cell 1 contains w cell 2 should equal x, if cell 1 contains y cell 2 should contain z

I'm trying to make an automated character sheet for D&D and for the equipment I would like to set it up so if the list of equipment the character has contains any individual weapon, the stats for making attack with that weapon appear in the attacks section. I've been using a formula referencing a table of all the statistics of all weapons on another part of the same sheet, and I can make it work for no more than two weapons. This is the formula:
=IF(OR(M13=A115);B115;IF(M13=A116;B116))
M13 is the the list of equipment the character has
A115=Club
B115=1d4 BL
A116=Greatclub
b116=1d8 BL
Note that the first part of the IF function is an OR function and the second part is another IF function. I don't know if that means you can only have one IF and one OR function in the overall IF function, but it will not work if I try changing the second IF function to an OR function, giving me error 504 and if I try changing the OR function to an IF function I get #VALUE!
To put it in simpler terms if cell C1=A1 D1 should equal B1. If C1=A2 D1 should equal B2 and so on.
I see where your going with that IF formula (I think), but what I think you really want is a =VLOOKUP:
=VLOOKUP(M13, A115:B200, 2, false)
This will search the range A115:A200 for the value in M13. When it finds it, it will stick the value from the corresponding B row into the cell where this formula exists.

Different approach to my situation

on a excel sheet I've got columns, each column represents a weeknumber.
I want to calculate the so-called 4 wk average for each row and for each week and this is the formula I use:
((value*Tvalue)+(value*Tvalue)+(value*Tvalue)+(value*Tvalue))/(Tvalue) (this is not the actual formula but simplified, that's not really important).
It's the checks that make things a bit more complex. If a value of a weeknr is zero, skip it, but if the next value is also zero, just skip the formula alltogether and make it a zero (or text like "false"). So another thing that has to be accounted for is that if a value is zero, the next weeks value is taken instead.
Example (see included file):
I want to calculate the formula (mov 4wk avg) for the third value for week 12, which will make the formula (0.2*6)+(0.3*6) now there's a zero on week 14 so I skip it, then formula will be:
(0.2*6)+(0.3*6)+(0.6*6)+(0.9*6)/(6). Hope that made some sense.
Right now I'm doing this in VBA with a lot of variables and a lot of if statements.
Is there an easier more effective way to go about this?
Example sheet
https://dl.dropbox.com/u/3121767/Book1.xlsx
PS I know the example sheet is a 2007/2010 version but I need to accomplish this for 2003
Array formula could be used (Ctrl-Shift-Enter in formula window, curled brackets will be inserted by Excel itself, not by a user):
A3: T value for row 3
B3:E3: values for single weeks in row 3
={IF(OR(SUM(IF((B3:C3)=0;1;0))>1;SUM(IF((C3:D3)=0;1;0))>1;SUM(IF((D3:E3)=0;1;0))>1);"Fail";(B3*$A3+C3*$A3+D3*$A3+E3*$A3)/$A3)}
The formula takes pairs of weeks, if the sum of the pair is 0, the whole formula will fail. If there's only one zero, everything will remain the same, as 0*value is equal to skip.
The formula can be copied to the right and downwards.
The updated exampe is available at http://www.bumpclub.ee/~jyri_r/Excel/4_week_average.xls
I tried a 2-step approach
1) transform each cell according to following rules:
if myweek = 0 and mynextweek = 0 then
myweek = 0
elseif myweek = 0 and mynextweek <> 0 then
myweek = mynextweek
else
myweek = myweek
endif
in Sheet2!B2 I entered =IF(AND(Sheet1!B2=0,Sheet1!C2=0),0,IF(Sheet1!B2=0,Sheet1!C2,Sheet1!B2)) and copied to all cells where in Sheet1 dat aexists, together with a copy of the base value in column A
2) Then I create a standard moving average across 4 weeks, for each set of 4 columns, starting with W15 in column M ... matter of taste if you display this in Sheet1 or Sheet2

Resources