Build string in VBscript based on array of groups - arrays

I've got an ADO query (ADODB.Recordset) in VBscript that will return a result like below:
nId wstrName nParentId
0 Managed computers 2
1 Unassigned computers NULL
2 Master Server NULL
3 pseudohosts NULL
5 Server 2 0
8 Group100 5
10 Group22 5
11 Group47 5
13 Group33 5
14 Group39 5
15 Group11 5
I need to build a complete location string based on the result when I know the top level group ID.
E.g. if the top level group ID is 11 then the complete location string will be "Master Server/Managed computers/Server 2/Group47" after traversing the groups by looking at the "nId" and "nParentId" values.
The number of parent groups can vary, so I need to loop until I reach a group without a parent group. I would also like to avoid making multiple SQL queries so I'm assuming the result should get loaded into an array and then handle the information from there.
What is the best way to handle this?
Thanks in advance :)

You can work with the recordset as it is. Try this:
groupname = "..."
rs.MoveFirst
rs.Find("wstrName = '" & groupname & "'")
location = rs("wstrName")
parent = rs("nParentId")
Do Until parent = "NULL"
rs.MoveFirst
rs.Find("nId = " & parent)
location = rs("wstrName") & "/" & location
parent = rs("nParentId")
Loop
You may need to adjust the condition of the loop depending on whether the NULL values in your recordset are the string "NULL" or actual Null values.

Use a Dictionary to store your tabular data and a recursive function to build the location string.
Demo script:
Dim dicData : Set dicData = CreateObject("Scripting.Dictionary")
' nId wstrName nParentId
dicData( 0) = Array("Managed computers" , 2 )
dicData( 1) = Array("Unassigned computers", NULL)
dicData( 2) = Array("Master Server" , NULL)
dicData( 3) = Array("pseudohosts" , NULL)
dicData( 5) = Array("Server 2" , 0 )
dicData( 8) = Array("Group100" , 5 )
dicData(10) = Array("Group22" , 5 )
dicData(11) = Array("Group47" , 5 )
dicData(13) = Array("Group33" , 5 )
dicData(14) = Array("Group39" , 5 )
dicData(15) = Array("Group11" , 5 )
Dim nId
For Each nId In dicData.Keys()
WScript.Echo Right(100 + nId, 2), buildLoc(dicData, nId, Array())
Next
Function buildLoc(dicData, nId, aTmp)
ReDim Preserve aTmp(UBound(aTmp) + 1)
aTmp(UBound(aTmp)) = dicData(nId)(0)
If IsNull(dicData(nId)(1)) Then
reverseArr aTmp
buildLoc = Join(aTmp, "/")
Else
buildLoc = buildLoc(dicData, dicData(nId)(1), aTmp)
End If
End Function
Sub reverseArr(aX)
Dim nUB : nUB = UBound(aX)
Dim nUB2 : nUB2 = nUB \ 2
Dim i, vt
For i = 0 To nUB2
vt = aX(i)
aX(i) = aX(nUB - i)
aX(nUB - i) = vt
Next
End Sub
output:
00 Master Server/Managed computers
01 Unassigned computers
02 Master Server
03 pseudohosts
05 Master Server/Managed computers/Server 2
08 Master Server/Managed computers/Server 2/Group100
10 Master Server/Managed computers/Server 2/Group22
11 Master Server/Managed computers/Server 2/Group47
13 Master Server/Managed computers/Server 2/Group33
14 Master Server/Managed computers/Server 2/Group39
15 Master Server/Managed computers/Server 2/Group11

Related

how do I insert values while using Hash.Lib while using while loop?

I have the following code... How would I be able to insert values in the array list with different indexes while its looping inside of a while loop? from the 2nd function(HashMine(CarID1))
local function HistoryHash() -- This function is to print out the Hashes "Mined" using Hash.Lib
for Hashindex = 1, #HashHistory do
print("Hash "..Hashindex..":", HashHistory[Hashindex])
end
end
--Mines the BTC pending transaction
local function HashMine(CarID1)
while stringtohash:sub(1,2) ~= "00" do
STRINGTOHASH = stringtohash..HASHNUMBER
stringtohash = HASHLIBRARY.sha256(STRINGTOHASH)
HASHNUMBER = HASHNUMBER + 1
wait(1)
table.insert()
end
HashGUI.Text = stringtohash
PendingTextGui.Text = ""
local CarID1 = CarBought
if CarID1 == 1 then
ConfirmedText.Text = ("Car1 ".. game.Workspace.Cars.Car1Buy.Car1.Value .. "BTC To Malta Car Dealer from " .. Players:GetChildren()[1].Name)
AfterCarPurchase()
elseif CarID1 == 2 then
ConfirmedText.Text = ("Car2 ".. game.Workspace.Cars.Car2Buy.Car2.Value.. "BTC To Malta Car Dealer from " .. Players:GetChildren()[1].Name)
AfterCarPurchase()
elseif CarID1 == 3 then
ConfirmedText.Text = ("Car3 ".. game.Workspace.Cars.Car3Buy.Car3.Value .. "BTC To Malta Car Dealer from " .. Players:GetChildren()[1].Name)
end
AfterCarPurchase()
end
table.insert() will cause the error message
bad argument #1 to 'insert' (table expected, got no value)
According to the Lua 5.4 Reference Manual - table.insert, it is mandatory to provide the table you want to insert to and the value you want to to insert into that table.
table.insert (list, [pos,] value)
Inserts element value at position pos in list, shifting up the
elements list[pos], list[pos+1], ยทยทยท, list[#list]. The default value
for pos is #list+1, so that a call table.insert(t,x) inserts x at the
end of the list t.
If you want to assign a value to a specific table index you need to use indexing assignmet t[key] = value

CLASSIC ASP - Do While / Loop with 3 conditions issue

I Have a SELECT with:
STATUS -1, 0 and 1.
The SELECT Statment:
SQL= "SELECT * FROM MYTABLE ORDER BY STATUS DESC"
SET MYDB = conn.Execute(SQL)
My issue:
Divide the SELECT in two parts with DO WHiLE/LOOP
PART 1:
"NOT EOF" of course
ALL STATUS 1 (priority and overule register limit)
Limit to XX registers (variable - TOTALREG)
NO STATUS -1
** STATUS 1 is the "Approved" status and can overrule the limit of registers.
I have a classroom with 20 students. (limit of registers)
but I can overbook this and make the class with 21, 22, 23 students - with "STATUS 1" = approved.
If I have only 15 approved - I will complete the limit of registers with the first 5 "STATUS 0" (Waiting for approval).
PART 2:
the rest of the SELECT
I Got a PARTIAL solution with this:
DO WHILE (((NOT MYDB.EOF) AND (CINT(COUNTREG) <= CINT(TOTALREG))) OR ((NOT MYDB.EOF) AND (MYDB("STATUS") > 0 ))) AND ((NOT MYDB.EOF) AND (MYDB("STATUS") > -1 ))
IF we have vacancies: (NOT MYDB.EOF) AND (CINT(COUNTREG) <= CINT(TOTALREG))
IF the register is approved: (NOT MYDB.EOF) AND (MYDB("STATUS") > 0 )
Exclude non-approved registers (status -1): (NOT MYDB.EOF) AND (MYDB("STATUS") > -1 )
- COUNTREG = will be incremented for each register inside the LOOP (countreg = countreg + 1)
- TOTALREG = Is a variable (number of person allowed in the classroom)
Its works with all situation.. but when I don't have registers with STATUS = -1 - I got an error '80020009'
why? any idea?

how to create multi line chart with single datatable in vb.net

I am working on vb.net application where i have to create a multi line chart. The table coming from the database using storing procedure is:-
TagName On Off Trip
P1 0 0 1
P2 0 1 1
P3 0 1 0
Q1 0 1 0
Q2 1 0 1
Q3 2 2 2
W1 4 2 1
W2 2 0 1
W3 1 1 0
W4 0 1 1
W5 2 1 1
And the code in vb.net i used to bind the chart named "chTrend" is:-
ds = ObjTags.GetTrendData()
If (ds.Tables(0).Rows.Count > 0) Then
dt = ds.Tables(0)
chTrend.DataSource = dt
chTrend.Series(0).XValueMember = "TagName"
chTrend.Series(0).YValueMembers = "On"
chTrend.Series(1).XValueMember = "TagName"
chTrend.Series(1).YValueMembers = "Off"
chTrend.Series(1).XValueMember = "TagName"
chTrend.Series(1).YValueMembers = "Trip"
For i = 0 To 2
chTrend.Series(i).ChartType = SeriesChartType.Line
chTrend.Series(i).IsVisibleInLegend = True
chTrend.Series(i).IsValueShownAsLabel = True
chTrend.Series(i).ToolTip = "Data Point Y Value #VALY{G}"
chTrend.Series(i).BorderWidth = 3
Next
End If
When i run the program a Error is coming as following
"Index was out of range. Must be non-negative and less than the size of the collection.Parameter name: index"
At the position
chTrend.Series(0).XValueMember = "TagName"
how to solve this?
Assuming that your DataTable only has the four DataColumns {TagName, On. Off. Trip}, then replace everything in your shown code below the line:
chTrend.DataSource = dt
with this.
chTrend.Series.Clear() ' clears any existing series
Dim s As Series
For columnIndex As Int32 = 1 To dt.Columns.Count - 1
Dim name As String = dt.Columns(columnIndex).ColumnName
s = chTrend.Series.Add(name)
s.XValueMember = dt.Columns(0).ColumnName
s.YValueMembers = name
s.ChartType = SeriesChartType.Line
s.IsVisibleInLegend = True
s.IsValueShownAsLabel = True
s.ToolTip = "Data Point Y Value #VALY{G}"
s.BorderWidth = 3
Next
chTrend.DataBind() ' loads the data from dt to the chart
The Chart databinding is a not a binding in the normal sense of binding. You need to tell the chart to copy the data from the source so that it has something to plot. That is what the DataBind method does.

creating a hierarchy using do loop

I'm trying to build a hierarchy from two columns where by one column is a client identifier and the other is its direct parent but I have an issue because a client can have a parent which can have another parent.
At the moment I have a number of merge statements in a macro that
%macro hierarchy (level);
data sourcedata (drop = PARENT_ID);
merge sourcedata (in = a)
inputdata (in = b);
by CLIENT_ID;
if a;
length Parent_L&level $32.;
Parent_L&level = PARENT_ID;
if Parent_L&level = Parent_L%eval(&level-1) then Parent_L&level ="";
CLIENT_ID = Parent_L&level;
proc sort;
by Parent_L&level;
run;
%mend;
%hierarchy(2)
%hierarchy(3)
%hierarchy(4)
my output looks like
client_ID Parent_L1 Parent_L2 Parent_L3 Parent_L4
clientA clientB . . .
ClientE clientA clientB . .
what I'm looking for is a way to do this until the last parent_Ln is all blank as I'm not sure how many levels I need to go to
thanks
The length you need is the depth of the tree.
It is a bit cumbersome to compute that in SQL, since you really need a hash table, or at least arrays.
You could use a hash in data step or ds2 to access the parent from the child.
If you have SAS/OR, then it is easier:
you can solve a shortest path and produce your table from
the paths from the roots of the forest.
For this example I will use the dataset from the link Reeza provided:
data have;
infile datalines delimiter='|';
input subject1 subject2;
datalines;
2 | 4
2 | 5
2 | 6
2 | 8
4 | 7
4 | 11
6 | 9
6 | 10
6 | 12
10 | 15
10 | 16
13 | 14
16 | 17
;
proc optmodel printlevel=0;
set<num,num> REFERRALS;
set CLIENTS = union{<u,v> in REFERRALS} {u, v};
set ROOTS = CLIENTS diff setof{<u,v> in REFERRALS} v;
read data have into REFERRALS=[subject1 subject2];
/* source, sink, seq, tail, head. */
set<num,num,num,num,num> PATHS;
num len{ROOTS,CLIENTS} init .;
num longest = max(of len[*]);
solve with NETWORK / graph_direction = directed
links = ( include = REFERRALS )
out = ( sppaths = PATHS spweights = len )
shortpath = ( source = ROOTS )
;
num parent{ci in CLIENTS, i in 1 .. longest} init .;
for{<u, v, i, s, t> in PATHS}
parent[v, len[u,v] - i + 1] = s;
print parent;
create data want from [client]=CLIENTS
{i in 1 .. longest} <COL('Parent_L'||i) = parent[client,i]>;
quit;

Calendar buttons aren't being removed correctly - Lua

I'm trying to make a calendar to be able to switch from month to month. My problem is in removing each day button when the next or previous buttons are touched.
Here is my code for the Previous Button to switch from the current month to the previous month. My Next button code is almost exactly the same. It works perfectly fine when I tap the button for the first time, but when I tap it again, I get an error at the child:removeSelf() line, and the print message tells me there are 61 elements in the table. It seems to add extra buttons to the table every time I go to a month that hasn't been seen yet.
This is really frustrating to me because I don't see any reason why the code is making extra buttons for every month, and even if it does, each one should still get removed when the button is tapped. Can someone please help me?
local prev_function = function(event)
if event.phase == "release" then
today.year = 2012
today.month = 3
today.day = 29
today.wday = 5
if monthNum == 1 then
monthNum = 12
yearNum = yearNum - 1
elseif monthNum ~= 1 then
monthNum = monthNum - 1
end
local month = ""
if monthNum == 1 then month = "January"
elseif monthNum == 2 then month = "February"
elseif monthNum == 3 then month = "March"
elseif monthNum == 4 then month = "April"
elseif monthNum == 5 then month = "May"
elseif monthNum == 6 then month = "June"
elseif monthNum == 7 then month = "July"
elseif monthNum == 8 then month = "August"
elseif monthNum == 9 then month = "September"
elseif monthNum == 10 then month = "October"
elseif monthNum == 11 then month = "November"
elseif monthNum == 12 then month = "December"
end
monthText.text = month .. " " .. yearNum
print("Table elements before button deletion: " .. #buttonTable)
for i = #buttonTable, 1, -1 do
--[[if button[i] ~= nil then
table.remove(buttonTable)
button[i]:removeSelf()
button[i] = nil
end--]]
local child = table.remove(buttonTable)
if child ~= nil then
child:removeSelf()
child = nil
end
end
print("Table elements after button deletion: " .. #buttonTable)
next_button.alpha = 1
for i = 1, math.floor(numYears * 365.25) do
dateTable[i] = calendar.getInfo(today) --calculate the next day's date
if dateTable[i].year == yearNum and dateTable[i].month == monthNum then -- create a button if the date's year and month match the desired month
button[i] = ui.newButton{
default = "images/day.png",
over = "images/dayover.png",
text = dateTable[i].day,
size = 30,
font = native.systemFontBold,
textColor = {0, 0, 0, 255},
onEvent = addExpense_function,
offset = -35 }
if dateTable[i].wday == 1 then button[i].x = math.floor(col/2)
elseif dateTable[i].wday == 2 then button[i].x = (col * 1) + math.floor(col/2)
elseif dateTable[i].wday == 3 then button[i].x = (col * 2) + math.floor(col/2)
elseif dateTable[i].wday == 4 then button[i].x = (col * 3) + math.floor(col/2)
elseif dateTable[i].wday == 5 then button[i].x = (col * 4) + math.floor(col/2)
elseif dateTable[i].wday == 6 then button[i].x = (col * 5) + math.floor(col/2)
elseif dateTable[i].wday == 7 then button[i].x = (col * 6) + math.floor(col/2)
end
if dateTable[i].day == 1 then button[i].y = wDayBar.y + wDayBar.height/2 + math.floor(row/2)
elseif dateTable[i].wday == 1 then button[i].y = button[i-1].y + row
else button[i].y = button[i-1].y
end
end
today = dateTable[i]
table.insert(buttonTable, button[i])
--button[i].id = "button_" .. i
end
print("Table elements after button creation: " .. #buttonTable)
end
return true
end
The reason why the code in the question doesn't work (and putting the table.insert inside the if...then does work) is due to the way you're using the button table.
The loop that starts for i = 1, math.floor(numYears * 365.25) do is going to create indices from 1 to a few hundred/thousand (depending on numYears).
However, as you're using button[i]= for filling the table and you're only filling 30 or so at a time, what you're creating is a sparse table with a few non-nil entries somewhere in the middle of the table.
Now with table.insert(buttonTable, button[i]) outside the if..then what actually happens is that most of the "inserts" are inserting nil. First time around this actually works ok for 2 reasons:
inserting nil on an empty table does nothing nor does inserting nil at the end of a table
there are only a month's worth of non-nil entries in button so only a month's worth will be inserted into buttonTable
With button and buttonTable setup like this, the first part of the call to the previous or next functions works as expected and removeSelf will be called on the month's worth of buttons. However this doesn't actually remove the button from the button table.
So when you come to the numYears loop again, not only will you add your freshly created buttons to both button and buttonTable, you'll also still have the buttons that you've just called removeSelf on in button so these will be added to buttonTable again. Crucially though, they are just tables now, so when you call removeSelf on them the second time it barfs. I presume this is the cause of the error you saw.
Moving table.insert(buttonTable, button[i]) to the if...then will resolve this problem as it will only ever add freshly minted buttons to buttonTable that are then removed each time next or previous are called.
A word of caution though. The button table is a bit of a mess. After a bit of navigating around, it'll have a bunch of dead buttons (that can't be garbage collected unless you've declared the values as weak) plus a month of working buttons. If you were to try to do anything with it, the chances are that you'll get problems.
It's not clear from the code if you even need the button table. If it's not required elsewhere it would probably be safer to just hold the button references in buttonTable.
Aside from making a new table for months as well as column coordinates like Nicol suggested, I found that I needed to put the table.insert() command inside the if ... then structure. I'm not sure exactly why putting it immediately after the if ... then structure caused it to not work properly, but I'm guessing it's because the buttons are being created inside the structure.
local prev_function = function(event)
if event.phase == "release" then
--set date to start from
today.year = 2012
today.month = 2
today.day = 29
today.wday = 4
--determine new month number
if monthNum == 1 then
monthNum = 12
yearNum = yearNum - 1
elseif monthNum ~= 1 then
monthNum = monthNum - 1
end
--set month string
local month = monthTable[monthNum]
monthText.text = month .. " " .. yearNum
print("Table elements before button deletion: " .. #buttonTable)
--remove all elements in buttonTable
for i = #buttonTable, 1, -1 do
local child = table.remove(buttonTable)
if child ~= nil then
child:removeSelf()
child = nil
end
end
print("Table elements after button deletion: " .. #buttonTable)
next_button.alpha = 1
--hide prev_button if we get to the month after the month we started from
if monthNum == today.month + 1 and yearNum == today.year then
prev_button.alpha = 0
end
--generate dates for specified number of years
for i = 1, math.floor(numYears * 365.25) do
dateTable[i] = calendar.getInfo(today)
--create a button for each date inside desired month
if dateTable[i].year == yearNum and dateTable[i].month == monthNum then
button[i] = ui.newButton{
default = "images/day.png",
over = "images/dayover.png",
text = dateTable[i].day,
size = 30,
font = native.systemFontBold,
textColor = {0, 0, 0, 255},
onEvent = addExpense_function,
offset = -35 }
--set x and y
button[i].x = colTable[dateTable[i].wday]
if dateTable[i].day == 1 then button[i].y = wDayBar.y + wDayBar.height/2 + math.floor(row/2)
elseif dateTable[i].wday == 1 then button[i].y = button[i-1].y + row
else button[i].y = button[i-1].y
end
table.insert(buttonTable, button[i])
end
--change 'today' for next iteration in the for loop
today = dateTable[i]
end
print("Table elements after button creation: " .. #buttonTable)
end
return true
end

Resources