Given an enumeration defined like so:
enum DebugModeType {
DebugModeNone = 0,
DebugModeButton = 1,
DebugModeFPS = 2,
DebugModeData = 4
};
#define DebugMode DebugModeButton|DebugModeData
I expect the value of DebugMode&DebugModeFPS to be 0, but I observe it to be 1.
You need parentheses in your macro to overcome operator precedence:
#define DebugMode (DebugModeButton|DebugModeData)
As-is:
DebugMode & DebugModeFPS
= DebugModeButton | DebugModeData & DebugModeFPS
(which is parsed as DebugModeButton | (DebugModeData & DebugModeFPS))
= DebugModeButton | (4 & 2)
= DebugModeButton | 0
= DebugModeButton
= 1
With parentheses as I suggest:
= (DebugModeButton | DebugModeData) & DebugModeFPS
= 5 & DebugModeFPS
= 5 & 2
= 0
Related
I wrote a query in Access that produces the following result.
qryCalculateXY
EquipmentID, ZoneNumber, RowNumber, ColumnNumber, XCoordinate, YCoordinate, ComponentID
1, 0, 1, 1, 500, 600, 1
1, 0, 1, 20, 500, 1200, 1
.
.
.
.
This query quickly calculates 1000+ XY co-ordinates of PrimaryComponent based on adding very few rows (maximum 30) in the table. And I am very happy with this so far.
However, there are very few locations (maximum 20) where, I may have ComponentID changed. For that I've created a table as below that lists out all exceptions.
tblException
EquipmentID, ZoneNumber, RowNumber, ColumnNumber, ComponentID
1, 0, 1, 20, 2
I want to generate another query which would list out all rows from qryCalculateXY as it is where it does not find corresponding values of EquipmentID, ZoneNumber, RowNumber, ColumnNumber from table tblException. And replace the value of ComponentID from tblException where values of these four columns match in the table tblException.
The resulting query should look like this -
qryCalculateXYFinal
EquipmentID, ZoneNumber, RowNumber, ColumnNumber, XCoordinate, YCoordinate, ComponentID
1, 0, 1, 1, 500, 600, 1
1, 0, 1, 20, 500, 1200, 2
.
.
.
.
This would save lots of time from my side not to convert query into a table and then change specific values.
How can I achieve this?
Thanks,
Nimish
I tried the left joint but to no avail.
Use Nz in a simple query with a left join:
Select
qryCalculateXY.EquipmentID,
qryCalculateXY.ZoneNumber,
qryCalculateXY.RowNumber,
qryCalculateXY.ColumnNumber,
qryCalculateXY.XCoordinate,
qryCalculateXY.YCoordinate,
Val(Nz([tblException].[ComponentID],[qryCalculateXY].[ComponentID])) As ComponentID
From
qryCalculateXY
Left Join
tblException On
(qryCalculateXY.ColumnNumber = tblException.ColumnNumber
(qryCalculateXY.RowNumber = tblException.RowNumber) AND
(qryCalculateXY.ZoneNumber = tblException.ZoneNumber) AN
(qryCalculateXY.EquipmentID = tblException.EquipmentID);
Output:
assuming:
'table xy
----------------------------------------------------------------------------------------------------------------------------------------------------
| EquipmentID | ZoneNumber | RowNumber | ColumnNumber | XCoordinate | YCoordinate | ComponentID |
----------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | 0 | 1 | 1 | 500 | 600 | 1 |
----------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | 0 | 1 | 20 | 500 | 1200 | 1 |
----------------------------------------------------------------------------------------------------------------------------------------------------
' saved query qryCalculateXY:
SELECT tableXY.*
FROM tableXY;
QryCalculateXYFinal:
'qryCalculateXYFinal
SELECT qryCalculateXY.EquipmentID, qryCalculateXY.ZoneNumber, qryCalculateXY.RowNumber, qryCalculateXY.ColumnNumber, qryCalculateXY.XCoordinate, qryCalculateXY.YCoordinate, DLookUp("ComponentID","tblException","EquipmentID = " & [EquipmentID] & " AND ZoneNumber = " & [ZoneNumber] & " AND RowNumber = " & [RowNumber] & " AND ColumnNumber = " & [ColumnNumber]) AS ExceptionComponentID, IIf([ExceptionComponentID],[ExceptionComponentID],[qryCalculateXY].[ComponentID]) AS ComponentID, GetReplacementComponentID([ComponentID],[EquipmentID],[ZoneNumber],[RowNumber],[ColumnNumber]) AS C2
FROM qryCalculateXY;
'ExceptionComponentID
ExceptionComponentID: DLookUp("ComponentID","tblException","EquipmentID = " & [EquipmentID] & " AND ZoneNumber = " & [ZoneNumber] & " AND RowNumber = " & [RowNumber] & " AND ColumnNumber = " & [ColumnNumber])
'The fixed ComponentID
ComponentID: IIf([ExceptionComponentID],[ExceptionComponentID],[qryCalculateXY].[ComponentID])
'C2
C2: GetReplacementComponentID([ComponentID],[EquipmentID],[ZoneNumber],[RowNumber],[ColumnNumber])
'GetReplacementComponentID in code module
Public Function GetReplacementComponentID(ComponentID As Long, EquipmentID As Long, Zonenumber As Long, RowNumber As Long, ColumnNumber As Long)
Dim returnvalue As Long
returnvalue = Nz(DLookup("ComponentID", "tblException", "(EquipmentID = " & EquipmentID & ") AND (ZoneNumber = " & Zonenumber & ") AND (RowNumber = " & RowNumber & ") AND (ColumnNumber = " & ColumnNumber & ")"), ComponentID)
GetReplacementComponentID = returnvalue
End Function
as shown above you can look up the appropriate ComponentID in the query. ExceptionComponentID is just there to make reading easier you can replace it with its expression everywhere it occurs or better yet abstract even more of the Calculations to a public function like in c2. You can cut, paste, import the tables and sql into your version of Access. You can also replace the vba functions with a subquery which is not shown.
I'm needing to take one array (firstArray) and input into a second array (secondArray). However, the first four fields are the same value. After the first four positions, it begins to alternate in values.
Example:
firstArray
+---------+
| ID# |
| Name |
| month1 |
| month2 |
| month3 |
| etc... |
+---------+
secondArray
+----------+
| ID# |
| Name |
| month1 |
| month2 |
| NewField |
| month3 |
| NewField |
| month4 |
| etc... |
+----------+
I'm fairly new to VBA, so I apologize for the awful code.
Code so far:
Dim i As Integer
i = 0
Dim j As Integer
ReDim secondArray(0 To (fieldCount - 4) * 2)
Dim finalCountDown As Integer
finalCountDown = (fieldCount - 4) * 2
secondArray(0) = firstArray(0)
secondArray(1) = firstArray(1)
secondArray(2) = firstArray(2)
secondArray(3) = firstArray(3)
i = 3
j = 3
Do Until i > finalCountDown
i = i + 1
secondArray(i) = "NewField"
i = i + 1
j = j + 1
secondArray(i) = firstArray(j)
Loop
I also have a MsgBox to iterate through and output my fields:
'//------ testing output
i = 0
For i = 0 To finalCountDown
MsgBox secondArray(i)
Next i
I appreciate any help! If there's any confusion, I'll gladly try to explain some more!
EDIT:
The two arrays are of different size but are dynamic. firstArray is firstly set to 20 positions while secondArray is originally set to 32 positions. (These are calculated each time this process is ran with the archived data being pulled. This allows my users to add data and not have to worry about having to manually add in the values to my arrays.)
EDIT2:
I've added Erik's portion to my code with a few alterations. I also added a separate counter for my firstArray in order to make sure it's inputting the correct rows into the correct positions of my secondArray.
EDIT3:
Here is the code that ended up working for me:
Dim i As Integer
i = 0
Dim j As Integer
'removed the " - 4"
ReDim secondArray(0 To (fieldCount * 2))
Dim finalCountDown As Integer
'removed the " - 4"
finalCountDown = (fieldCount * 2)
secondArray(0) = firstArray(0)
secondArray(1) = firstArray(1)
secondArray(2) = firstArray(2)
secondArray(3) = firstArray(3)
i = 3
'created own counter for firstArray
j = 3
Do Until i > finalCountDown
i = i + 1
secondArray(i) = "NewField"
i = i + 1
j = j + 1
secondArray(i) = firstArray(j)
Loop
The error I was getting was due "Subscript not in Range" due to the fact that my finalCountDown variable was less than my array needed to be. Allowing the variable to become larger than my array allowed my array to finish iterating through itself and now inputs the proper fields in the proper order.
I'm accepting Erik's answer as it was the stepping stone to answering the question!
For the adjusted code, you can do a simple check to check if the j value is valid:
Dim i As Integer
i = 0
Dim j As Integer
ReDim secondArray(0 To (fieldCount - 4) * 2)
Dim finalCountDown As Integer
finalCountDown = (fieldCount - 4) * 2
secondArray(0) = firstArray(0)
secondArray(1) = firstArray(1)
secondArray(2) = firstArray(2)
secondArray(3) = firstArray(3)
i = 3
j = 3
Do Until i > finalCountDown
i = i + 1
finalArray(i) = "NewField"
i = i + 1
j = j + 1
If j => LBound(colheaders) And j <= UBound(colHeaders) Then
finalArray(i) = colHeaders(j)
End If
Loop
I've been working on a homework problem for a few hours now and cannot for the life of me figure out how to get it to work.
The premise of the program is:
-User inputs number
-Display a multiplication table from 1-9 of that users number
if they entered 4 I need to show
1 * 4 = 4
2 * 4 = 8
.
.
.
9 * 4 = 36
Here is what I (unsuccessfully) have for my loop so far:
Dim userNum As Integer = numInputTextBox.Text
Dim tableDisplay As String
Dim i As Integer = 1
Do While i <= 9
tableDisplay = userNum * i
tableTextBox.Text = tableDisplay
i += 1
Loop
(tableTextBox is where the output will be stored)
The only output I get is the result of the last iteration of the loop so if I entered 7, the output I get is 63 (7 * 9)
I'm unsure how to continually add to a string and output it to the textbox while in a loop.
Any and all help is greatly appreciated. My apologies for the sloppy formatting.
Here is an idea of what I am talking about in my comment:
Dim userNum As Integer = numInputTextBox.Text
Dim tableDisplay As String
Dim i As Integer = 1
Do While i <= 9
tableDisplay = userNum & " * " & i & " = " & userNum * i & vbLf
i += 1
Loop
tableTextBox.Text = tableDisplay
Although I wouldn't use a while loop in this instance, I would use a for next like so:
Dim userNum As Integer = numInputTextBox.Text
Dim tableDisplay As String
Dim i As Integer
For i = 1 To 9
tableDisplay = userNum & " * " & i & " = " & userNum * i & vbLf
Next
tableTextBox.Text = tableDisplay
I have an array of 18 questions. Each question has 4 possibilities of answer ranging from 1 to 4. I'd like to count how many people answered question1 and so on. My codes below. Do you have a better way to do it? I can't list all 18 questions like that.
Dim question(18) as string
Dim ans1Arr() As String = {0, 0, 0, 0}
Dim ans2Arr() As String = {0, 0, 0, 0}
If ques(0) = 1 Then
ans1Arr(0) = ans1Arr(0) + 1
ElseIf ques(0) = 2 Then
ans1Arr(1) = ans1Arr(1) + 1
ElseIf ques(0) = 3 Then
ans1Arr(2) = ans1Arr(2) + 1
ElseIf ques(0) = 4 Then
ans1Arr(3) = ans1Arr(3) + 1
End If
If ques(1) = 1 Then
ans2Arr(0) = ans2Arr(0) + 1
ElseIf ques(1) = 2 Then
ans2Arr(1) = ans2Arr(1) + 1
ElseIf ques(1) = 3 Then
ans2Arr(2) = ans2Arr(2) + 1
ElseIf ques(1) = 4 Then
ans2Arr(3) = ans1Arr(3) + 1
End If
You can use a Lookup(Of TKey, TElement) which is similar to a dictionary apart from the fact that it returns an empty sequence if the key is not available:
Dim lookup = question.ToLookup(Function(qNum) qNum)
Dim countAnswerOne As Int32 = lookup(1).Count()
Dim countAnswerTwo As Int32 = lookup(2).Count()
' ... '
Can be tested easily with:
Dim question(18) As Int32
Dim rnd As New Random()
For i As Int32 = 0 To 17
question(i) = rnd.Next(1, 5)
Next
Dim lookup = question.ToLookup(Function(qNum) qNum)
Console.Write("One: {0} Two: {1} Three: {2} Four: {3}",
lookup(1).Count(), lookup(2).Count(), lookup(3).Count(), lookup(4).Count())
which outputs f.e: One: 5 Two: 6 Three: 5 Four: 2
I have variables el1, el2,....el16 and c1, c2,....c16 and Counter
Would like to use in a counting loop
For Counter = 1 to 16
If el1 = "x" Then
el1 = 0
c1 = 0
Else
c1 = 1
End If
Next
The If statement works fine with defined variables. How can I combine the "Counter" variable with the "el" and "c" in the loop to recognize as el1, c1, el2, c2,...el16, c16
Here is the final version of the script. It worked fine in Windows 7 version of ArcPad, but the If statement blew up on the mobile device using mobile vbscript runtime libraries. The variable array method might work better, but I wasn't quite sure how to patch it in. Any help would be appreciated.
Sub findelement
Dim el1, el2, el3, el4, el5, el6, el7, el8, el9, el10, el11, el12, el13, el14, el15, el16, scoreA, scoreB, calc
el1 = EDITFORM.Pages.Item("page4").Controls.Item("element1")
el2 = EDITFORM.Pages.Item("page4").Controls.Item("element2")
el3 = EDITFORM.Pages.Item("page4").Controls.Item("element3")
el4 = EDITFORM.Pages.Item("page4").Controls.Item("element4")
el5 = EDITFORM.Pages.Item("page4").Controls.Item("element5")
el6 = EDITFORM.Pages.Item("page4").Controls.Item("element6")
el7 = EDITFORM.Pages.Item("page4").Controls.Item("element7")
el8 = EDITFORM.Pages.Item("page4").Controls.Item("element8")
el9 = EDITFORM.Pages.Item("page5").Controls.Item("element9")
el10 = EDITFORM.Pages.Item("page5").Controls.Item("element10")
el11 = EDITFORM.Pages.Item("page5").Controls.Item("element11")
el12 = EDITFORM.Pages.Item("page5").Controls.Item("element12")
el13 = EDITFORM.Pages.Item("page5").Controls.Item("element13")
el14 = EDITFORM.Pages.Item("page5").Controls.Item("element14")
el15 = EDITFORM.Pages.Item("page5").Controls.Item("element15")
el16 = EDITFORM.Pages.Item("page5").Controls.Item("element16")
Dim c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, Counter
For Counter = 1 to 16
If "x" = eval ("el" & Counter) Then
execute "el" & Counter & " = 0"
execute "c" & Counter & " = 0"
Else
execute "c" & Counter & " = 1"
End If
Next
'do math
scoreA = CInt(el1) + CInt(el2) + CInt(el3) + CInt(el4) + CInt(el5) + CInt(el6) + CInt(el7) + CInt(el8) + CInt(e9) + CInt(el10) + CInt(el11) + CInt(el12) + CInt(el13) + CInt(el14) + CInt(el15) + CInt(el16)
scoreB = CInt(c1) + CInt(c2) + CInt(c3) + CInt(c4) + CInt(c5) + CInt(c6) + CInt(c7) + CInt(c8) + CInt(c9) + CInt(c10) + CInt(c11) + CInt(c12) + CInt(c13) + CInt(c14) + CInt(c15) + CInt(c16)
calc = CDbl(scoreA) / CDbl(scoreB)
'vbscript assumes these are strings and appends them, to get the sum like you want cast them to a double (CDbl) or integer (CInt)
'MsgBox (scoreA)
'MsgBox (scoreB)
'MsgBox (calc)
'Return calculated data to form.....
EDITFORM.Pages("Results").Controls("sumEl").Value = (scoreA)
EDITFORM.Pages("Results").Controls("scoreB").Value = (scoreB)
EDITFORM.Pages("Results").Controls("calc").Value = (calc)
End Sub
You can use Execute, ExecuteGlobal and Eval to dynamically form variable names for expressions to execute:
Execute "el" & Counter & " = 42"
In general, Eval/Execute/ExecuteGlobal are dangerous, inefficient, and
unnecessary. There are exception (e.g. library/module import, (quick and dirty)
calculations based on user input), but I doubt that your (real) problem can't be
solved without such Voodoo.
Compare:
Dim el1, el2, el3
el1 = "a"
el2 = "x"
el3 = "b"
WScript.Echo "el:", el1, el2, el3
Dim c1, c2, c3
Dim i
For i = 1 to 3
If "x" = Eval("el" & i) Then
Execute "el" & i & " = 0"
Execute "c" & i & " = 0"
Else
Execute "c" & i & " = 1"
End If
Next
WScript.Echo "el:", el1, el2, el3
WScript.Echo " c:", c1, c2, c3
output:
el: a x b
el: a 0 b
c: 1 0 1
(idea stolen from Helen)
With:
Dim sEL : sEL = "a x b"
Dim oWAN : Set oWAN = WScript.Arguments.Named
If oWAN.Exists("el") Then sEL = oWAN("el")
Dim aEL : aEL = Split(sEL)
WScript.Echo "aEL:", Join(aEL)
ReDim aC(UBound(aEL))
Dim i
For i = 0 to UBound(aEL)
If "x" = aEL(i) Then
aEL(i) = 0
aC(i) = 0
Else
aC(i) = 1
End If
Next
WScript.Echo "aEL:", Join(aEL)
WScript.Echo " aC:", Join(aC)
output (no arg):
aEL: a x b
aEL: a 0 b
aC: 1 0 1
output (arg: /el:"a a a x b x x c x"):
aEL: a a a x b x x c x
aEL: a a a 0 b 0 0 c 0
aC: 1 1 1 0 1 0 0 1 0
I think, you'll agree that using a collection/array gives you as much flexibility
as the eval/execute approach.