Getting "Out of Stack space" error inconsistently - css

On every page of my workbook, I have a status bar made of status boxes. There are three statuses -- "Tab Started", "Design Updated", and "Configurations Complete". Originally I had these boxes called out on every page (and using absolute references), but I recently tried to improve the efficiency and flexibility of the workbook by moving that code to a separate module and calling it on every workbook page near the top (+ setting variables using "Find" rather than absolute references).
However, while this works 90% of the time or more, occasionally I get an error message "Out of Stack Space". Reading on the MSDN, none of the examples that might trigger this error seem to apply to my code (e.g. the code doesn't call itself).
See below for code.
'This function is called by all workbook tabs and controls the status boxes
Sub StatusBars(ByVal Target As Range)
Dim TabStarted1 As Range
Set TabStarted1 = ActiveSheet.Range("A4:Z5").Find("Tab Started")
Dim TabStarted As Range
Set TabStarted = TabStarted1.Offset(0, 1)
Dim Design1 As Range
Set Design1 = ActiveSheet.Range("A6:Z7").Find("Design Updated")
Dim Design As Range
Set Design = Design1.Offset(0, 1)
Dim Configurations1 As Range
Set Configurations1 = ActiveSheet.Range("A8:Z9").Find("Configurations Complete")
Dim Configurations As Range
Set Configurations = Configurations1.Offset(0, 1)
If Not Intersect(Target, TabStarted) Is Nothing Then
If Target.Cells.Count = 2 Then
If WorksheetFunction.CountA(Target) = 0 Then 'If box is empty, then add an X, format it, change the box color and the tab color
TabStarted.Value = "X"
TabStarted.HorizontalAlignment = xlCenter
TabStarted.Font.Size = 25
TabStarted.Interior.Color = RGB(255, 255, 0)
Design.Interior.Color = RGB(255, 255, 255)
Design.Value = ""
Configurations.Interior.Color = RGB(255, 255, 255)
Configurations.Value = ""
ActiveSheet.Tab.Color = RGB(255, 255, 0)
Else 'if box is already checked clear, the X, the color, and the tab color
TabStarted.Interior.Color = RGB(255, 255, 255)
TabStarted.Value = ""
ActiveSheet.Tab.ColorIndex = xlColorIndexNone
End If
End If
End If
If Not Intersect(Target, Design) Is Nothing Then
If Target.Cells.Count = 2 Then
If WorksheetFunction.CountA(Target) = 0 Then
Design.Value = "X"
Design.HorizontalAlignment = xlCenter
Design.Font.Size = 25
Design.Interior.Color = RGB(0, 112, 192)
TabStarted.Interior.Color = RGB(255, 255, 255)
TabStarted.Value = ""
Configurations.Interior.Color = RGB(255, 255, 255)
Configurations.Value = ""
ActiveSheet.Tab.Color = RGB(0, 112, 192)
Else
Design.Interior.Color = RGB(255, 255, 255)
Design.Value = ""
ActiveSheet.Tab.ColorIndex = xlColorIndexNone
End If
End If
End If
If Not Intersect(Target, Configurations) Is Nothing Then
If Target.Cells.Count = 2 Then
If WorksheetFunction.CountA(Target) = 0 Then
Configurations.Value = "X"
Configurations.HorizontalAlignment = xlCenter
Configurations.Font.Size = 25
Configurations.Interior.Color = RGB(0, 176, 80)
TabStarted.Interior.Color = RGB(255, 255, 255)
TabStarted.Value = ""
Design.Interior.Color = RGB(255, 255, 255)
Design.Value = ""
ActiveSheet.Tab.Color = RGB(0, 176, 80)
Else
Configurations.Interior.Color = RGB(255, 255, 255)
Configurations.Value = ""
ActiveSheet.Tab.ColorIndex = xlColorIndexNone
End If
End If
End If
End Sub
EDIT:
An example of the code that calls this function:
'Remove Case Sensitivity
Option Compare Text
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.ScreenUpdating = False
Dim var1 As Variant
Dim var2 As Variant
Dim var3 As Variant
Dim PlusTemplates As Range
Set PlusTemplates = Range("A14:Z15").Find("+")
Call StatusBars(Target)
[rest of the code]
Application.ScreenUpdating = True
End Sub

Activesheet is a global variable. When you set tabstarted1 etc. with Activesheet, because activesheet is on stack and did not disposed, your other variables like tabstarted1, design1 stays on stack memory. Try to get activesheet as parameter to your function.

I think the error is because your code changes the sheet and thus a new event is called. To make sure that this is the case, do the following - insert a STOP on the event like this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.ScreenUpdating = False
Stop
Dim var1 As Variant
'rest of your code.
End Sub
The first time you have a selection change you will stop on the stop. Then press F5 and continue. If you stop again, then it is a recursion error.
The easiest way to fix it is with Application.EnableEvents = False at the beginning of the event and Application.EnableEvents = True at the end of the code.

Related

Generating random numbers from 1 - 24 in vb.net

I'm trying to randomly generate a list of numbers from 1 - 24 separated by a pipe key. I've manage to get it working except that it generates the same exact number order every time "17|13|14|7|8|19|1|20|18|2|10|21|9|24|23|15|12|16|22|6|3|4|5|11". How do I get it to be truly random?
Public Function DoesNoAlreadyExistInList(TheNumber As Integer, TheList As String) As Boolean
Dim counter As Integer = 0
If (TheList = Nothing Or TheList = "") And Not (TheList.Contains("|")) Then
Else
Dim numberlist() As String = TheList.Split("|")
For Each n As String In numberlist
Dim n_ As Integer = n
If n_ = TheNumber Then
counter += 1
Else
counter += 0
End If
Next
End If
If counter = 0 Then
DoesNoAlreadyExistInList = False
Else
DoesNoAlreadyExistInList = True
End If
End Function
Protected Sub new_game_Click(sender As Object, e As EventArgs) Handles new_game.Click
Dim intNo As Integer
Dim blnExists As Boolean
Dim counter As Integer = 0
'Clear the listbox
player1_cards.Value = Nothing
'Do 25 times
For intI = 0 To 23
'Do this until we no the number is not already in the list
Do
'Get a random no 1 - 50
intNo = Int((24 * Rnd()) + 1)
'Check if the number is already in the list.
blnExists = DoesNoAlreadyExistInList(intNo, player1_cards.Value)
Loop Until blnExists = False
'Add the number into the listbox.
counter += 1
If counter = 1 Then
player1_cards.Value = player1_cards.Value & intNo
Else
player1_cards.Value = player1_cards.Value & "|" & intNo
End If
Next
right_player_number.Text = player1_cards.Value
End Sub
See answer from Peter O.
I placed "Randomize()" before "intNo = Int((24 * Rnd()) + 1)" in my code above that fixed my problem.
A list in .net refers to List(Of T) where T is the Type. I created a List(Of Integer) to hold the unique random numbers. Since you refer to adding number to listbox I assumed player1_cards is an
<asp:ListBox ID="NumbersListBox" runat="server" />
I just changed the ID to suit me. Not important.
I cleared the DataSource and the ItemsCollection or the list box.
I created an instance of the Random class (included in the .net framework) outside of the method. I can be used in any method in the Class. I used the .Next method to get a random number. I checked with the .Contains method of the list and added it to the list if it wasn't already there. After that, it exits the Do and continues with the For loop. If it does exist the Do loops again until a unique entry is returned.
Finally, set the DataSource of the list box and DataBind to display the numbers.
If all you need is the String I showed how to do that with String.Join.
Dim rand As New Random
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim intNo As Integer
Dim lst As New List(Of Integer)
'Clear the listbox
NumbersListBox.DataSource = Nothing
NumbersListBox.Items.Clear()
'Do 25 times ?????
'This does not loop 25 times; it loops 24 times
For intI = 0 To 23
Do
'Get a random no 1 - 50
'rand.Next(inclusive of first value, exclusive of second value)
intNo = rand.Next(1, 51)
'Check if the number is already in the list.
If Not lst.Contains(intNo) Then
lst.Add(intNo)
Exit Do
End If
Loop
Next
'Add the numbers into the listbox.
NumbersListBox.DataSource = lst
NumbersListBox.DataBind()
NumbersListBox.SelectedIndex = 0
right_player_number.Text = NumbersListBox.SelectedItem.ToString
'To put the numbers into a String separated by a |
Dim s = String.Join("|", lst)
Debug.Print(s)
End Sub
Your Function wasn't needed with this code.
If what you actually want is the numbers from 1 to 24 in random order then I would suggest the following:
Dim rng As New Random
Dim numbers = Enumerable.Range(1, 24).OrderBy(Function(n) rng.NextDouble())
You can add a ToArray call to the end of that second line if you want the randomised numbers in an array. What that does is basically generate a random value to represent each number and then sort the numbers by those random values. It is much like the overload of Array.Sort that sorts two concurrent arrays using one of them as keys to sort the other. If you wanted to do it manually, it would look like this:
Dim rng As New Random
Dim numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}
Dim keys = {rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble(),
rng.NextDouble()}
Array.Sort(keys, numbers)
If you want those numbers is a single String, separarted by pipes, do this:
Dim text = String.Join("|", numbers)
You don't need the ToArray call to do that as String.Join will accept an IEnumerable(Of T).
In case you're wondering, I used NextDouble instead of Next because it is more efficient. When generating a random Integer in a range, the first step is to generate a random Double, which is then scaled and rounded. Because these values are being used just for sorting, it's their randomness that matters and not their actual values. As such, the extra steps of scaling and rounding each random Double are pointless.

IDL: Button Widget stops updating after one push

I'm pretty new to IDL and as a way to learn I have tried to create a number guessing game. I have a Widget with three buttons: One that tells the program the number you are thinking of is larger than the one the computer asks about, one if it's smaller and one if it's correct.
My problem is that once you have pushed i.e. the larger button, if you press it again it won't do anything. E.g. the program starts to guess 500, if I press larger it guesses 750. If I now press larger again, the program doesn't respond.
My code is like this:
PRO test1_event, ev
WIDGET_CONTROL, ev.top, GET_UVALUE = stash
minimum = 0
maximum = 1000
IF (ev.Id EQ largerbutton) THEN BEGIN
minimum = (minimum+maximum)/2
maximum = maximum
ENDIF
IF (ev.Id EQ smallerbutton) THEN BEGIN
maximum = (minimum+maximum)/2
minimum = minimum
ENDIF
IF (ev.Id EQ correctbutton) THEN BEGIN
help2 = string('I got it!') ;This prints to a text widget
ENDIF
END
PRO test1
wBase = WIDGET_BASE(X_SCROLL_SIZE = 512, Y_SCROLL_SIZE = 512)
;wDraw = WIDGET_WINDOW(wBase, X_SCROLL_SIZE = 512, Y_SCROLL_SIZE = 512)
Lower = WIDGET_BUTTON(wBase, VALUE = 'Smaller', XOFFSET = 60, YOFFSET = 250)
Higher = WIDGET_BUTTON(wBase, VALUE = 'Larger', XOFFSET = 225, YOFFSET = 250)
Correct = WIDGET_BUTTON(wBase, VALUE = 'Correct', XOFFSET = 380, YOFFSET = 250)
minimum = 0
maximum = 1000
help1 = string('Please think of a number between' + string(minimum) + ' and ' + string(maximum))
help2 = string('Is your number ' + string((minimum + maximum)/2) + '?')
wText = WIDGET_TEXT(wBase, VALUE = ['Welcome to my little game. I will now try and guess a number you are thinking of.'], XSIZE = 63,XOFFSET = 50, YOFFSET = 100)
wText1 = WIDGET_TEXT(wBase, VALUE = help1, XSIZE = 63,XOFFSET = 50, YOFFSET = 120)
wText2 = WIDGET_TEXT(wBase, VALUE = help2, XSIZE = 63,XOFFSET = 50, YOFFSET = 140)
stash = {text1:wText, text2:wText1, text3:wText2, $
lower:Lower, higher:Higher, correct:Correct, minimum:minimum, maximum:maximum}
WIDGET_CONTROL, wBase, SET_UVALUE = stash, /REALIZE
XMANAGER, 'test1', wBase
end
I have tried using a while loop and also REPEAT, but then the program just goes right up to 999 if I press the larger button and to 0 if I press the smaller.
Any ideas to what I can do?
EDIT: Added the rest of the program
I think the buttons are working fine but your event handler doesn't actually do anything. First, I needed to change largerbutton, smallerbutton, and correctbutton to be stash.higher, stash.lower, stash.correct. Then, your code calculates the new minimum & maximum but it doesn't actually do anything with them.
I put a print statement into the event code and it's definitely getting the button presses.
In your event handler you probably want to use widget_control to update the text box with the new guess.

Invalid procedure call or argument: 'Mid'

I have a function (see below) and it works perfectly. I recently moved my code to another server and i did not change anything in it. It fails to run on new server.
Microsoft VBScript runtime error '800a0005'
Invalid procedure call or argument: 'Mid'
/calculate.asp, line 416
When i checked the line 416, i got this:
Dim result3: result3 = Mid(o3.responseText, Basla3, Bitir3)
and this is the complete function:
<%
Function xyz()
Dim o3: Set o3 = Server.CreateObject("MSXML2.ServerXMLHTTP")
Dim o_date3: o_date3 = split(EndingDate, ".")
Dim s_date3
If (Len(o_date3(2)) = 4) Then
s_date3 = o_date3(2)
Else
s_date3 = "20" & o_date3(2)
End If
If (Len(o_date3(1)) = 2) Then
s_date3 = s_date3 & o_date3(1)
Else
s_date3 = s_date3 & "0" & o_date3(1)
End If
If (Len(o_date3(0)) = 2) Then
s_date3 = s_date3 & o_date3(0)
Else
s_date3 = s_date3 & "0" & o_date3(0)
End If
Dim s3: s3 = "<soapenv:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:urn=""urn:AntTransferWSIntf-IAntTransferWS""><soapenv:Header/><soapenv:Body><urn:EURCurrency soapenv:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/""><DateStr xsi:type=""xsd:string"">" + s_date3 + "</DateStr></urn:EURCurrency></soapenv:Body></soapenv:Envelope>"
o3.Open "POST", serviceUrl, False
o3.setRequestHeader "Content-Type", "text/xml"
o3.setRequestHeader "Connection", "close"
o3.setRequestHeader "SOAPAction", " "
o3.send s3
Dim hataVarMiBasla3: hataVarMiBasla3 = (InStr(1, o3.responseText, "<faultstring>", vbTextCompare)) + 13
If (hataVarMiBasla3 > 13) Then
Dim hataVarMiBitir3: hataVarMiBitir3 = (InStr(1, o3.responseText, "</faultstring>", vbTextCompare)) - hataVarMiBasla3
Dim hata3: hata3 = Mid(o3.responseText, hataVarMiBasla3, hataVarMiBitir3)
KurGetir = hata3
Else
Dim Basla3: Basla3 = (InStr(1, o3.responseText, """xsd:double"">", vbTextCompare)) + 13
Dim Bitir3: Bitir3 = (InStr(1, o3.responseText, "</return>", vbTextCompare)) - Basla3
Dim result3: result3 = Mid(o3.responseText, Basla3, Bitir3)
xyz = CDbl(Replace(result3, ".", mstrComma))
End If
Set o3 = Nothing
End Function
%>
Why am i receiving this error?
Mid struct from MSDN
Mid(string, start[, length])
Not official reference but according to my experience, you get that error if
start is less than or equal to zero.
length is less than zero (if it is not missed in the Mid call)
Have a look at the error line and related ones.
Dim Basla3: Basla3 = (InStr(1, o3.responseText, """xsd:double"">", vbTextCompare)) + 13
Dim Bitir3: Bitir3 = (InStr(1, o3.responseText, "</return>", vbTextCompare)) - Basla3
Dim result3: result3 = Mid(o3.responseText, Basla3, Bitir3)
Lets suppose o3.responseText is empty because your code does not check whether the response is empty.
Basla3 can not be less than 13 according to InStr() + 13, so it's not the problem.
However it seems like Bitir3 can be less then zero according to InStr() - Basla3 (Basla3 evaluated as 13).
Continuing with the assumption, (InStr(1, o3.responseText, "</return>", vbTextCompare)) evaluated as 0, then with - Basla3 it will be evaluated as -13. Tada! rule 2 violated, length cannot be less than zero.
The problem with your code is, there is no check response length nor response status.
If the response is empty, consider the following:
Your new server may have connectivity problems unlike the old one.
The API which you have is authorized for the old server's IP address only.
In a nutshell, you should optimize the code and be sure that there is an xml response.
At least use something like that:
o3.Send
If o3.readyState = 4 And o3.status = 200 Then
If Len(o3.responseText) > 0 Then
'response is ready to parse
Else
'response status is ok but empty
End If
Else
'request failed
End If
BTW, due to your request is a soap call, I'd highly recommend done the job by parsing xml response using DomDocument etc.
Replacing decimal points, using Mid & InStr pair to check node existence are just trouble and bad practice also.
If I were to take a guess.
VBScript gives strange errors when your "MID" function has to deal with special characters, or what it thinks are non-string values.
So, o3.responseText probably contains text that it doesn't like.

Strange issue with repeater and cached dataset - only last row shown

I have a relatively simple piece of code as follows:
Dim oShow As DataSet = Nothing
Dim cacheKey As String = String.Format("AsyncCacheFor_agenda_{0}", ShowID)
If Not IsNothing(Cache(cacheKey)) Then
oShow = DirectCast(Cache(cacheKey), DataSet)
Else
oShow = DataServers.dsTMW.GetAgenda(ShowID, 0, "", 0, True)
Cache.Insert(cacheKey, oShow, Nothing, System.Web.Caching.Cache.NoAbsoluteExpiration, New TimeSpan(1, 0, 0))
End If
phSearch.Visible = True
oShowRow = oShow.Tables(0).Rows(0)
oTracks = oShow.Tables(1)
oSearchResults = oShow.Tables(5)
If Not IsNothing(oSearchResults) AndAlso oSearchResults.Rows.Count > 0 Then
rptSearch.Visible = True
phNoResults.Visible = False
rptSearch.DataSource = oSearchResults
rptSearch.DataBind()
Else
rptSearch.Visible = False
phNoResults.Visible = True
End If
"rptSearch" is a Repeater and the GetAgenda() method reads a dataset from the database via stored procedure. This dataset has 6 different tables. When the dataset is read from the database, the Repeater displays 36 rows, the expected result. When it's read from the cache it only displays one row, the last one. What's strange is that when I debug, I see that oSearchResults.Rows.Count = 36 in both cases.
Does anyone have any idea why this might happen?
To truly see if it has anything to do with the cache, try always using the Dataset from the cache. On the check to see if it is in the cache, rather than going and getting the Dataset and then using it, go get it, put it in the cache, then use it.
So, rather than this:
If Not IsNothing(Cache(cacheKey)) Then
oShow = DirectCast(Cache(cacheKey), DataSet)
Else
oShow = DataServers.dsTMW.GetAgenda(ShowID, 0, "", 0, True)
Cache.Insert(cacheKey, oShow, Nothing, System.Web.Caching.Cache.NoAbsoluteExpiration, New TimeSpan(1, 0, 0))
End If
Do this:
If IsNothing(Cache(cacheKey)) Then
oShow = DataServers.dsTMW.GetAgenda(ShowID, 0, "", 0, True)
Cache.Insert(cacheKey, oShow, Nothing, System.Web.Caching.Cache.NoAbsoluteExpiration, New TimeSpan(1, 0, 0))
End If
oShow = DirectCast(Cache(cacheKey), DataSet)
This won't "fix" your issue, but it will narrow down the isue. If you get 1 row always, then you know it has to do with pulling the Dataset out of the cache. If I had to guess though, I'd say that there is something else going on outside of your code snippet.
I figured out the problem. I was doing this in the ItemDataBound event:
Dim dvRows As DataView = oSearchResults.DefaultView
dvRows.RowFilter = String.Format("Submission_id={0} AND speaker_id Is Not Null", oRow("Submission_id"))
Once I changed that to:
Dim dvRows As DataView = oSearchResults.Copy().DefaultView
The problem went away. I wonder why this was only a problem when it was being cached.

NPOI set cell style "HSSFFont.BOLDWEIGHT_BOLD" is not working

I'm using NPOI to output excel from Asp.Net. I want to set bold and normal style to my cell but it is working for few cell and not for remaining cell.Please have look on following example:
Dim hssfworkbook As New HSSFWorkbook()
Dim sheetOne As HSSFSheet = hssfworkbook.CreateSheet("Sheet1")
hssfworkbook.CreateSheet("Sheet2")
hssfworkbook.CreateSheet("Sheet3")
Dim cellStyle As HSSFCellStyle = hssfworkbook.CreateCellStyle
cellStyle.Alignment = HSSFCellStyle.ALIGN_CENTER
Dim font As HSSFFont = _hssfworkbook.CreateFont()
font.Boldweight = HSSFFont.BOLDWEIGHT_BOLD
cellStyle.SetFont(font)
For i = 0 To 9 Step 1
'I want to add cell style to these cells
If i Mod 2 = 0 Then
Sheet1.CreateRow(i).CreateCell(1).SetCellValue(i)
font.Boldweight = HSSFFont.BOLDWEIGHT_BOLD
cellStyle.SetFont(font)
Sheet1.GetRow(i).GetCell(1).CellStyle = cellStyle
Else
Sheet1.CreateRow(i).CreateCell(1).SetCellValue(i)
font.Boldweight = HSSFFont.BOLDWEIGHT_NORMAL
cellStyle.SetFont(font)
Sheet1.GetRow(i).GetCell(1).CellStyle = cellStyle
End If
Next
Actually code is working fine but i don't know the particular situation from where and why its stops working for remaining few rows. Its not working properly for all cells and from that particular cell the bold and normal property stops working on whole sheet like sheet2 and sheet3.
You have to use multiple styles because a change to a style affects everywhere that style is referenced in the sheet.
Dim hssfworkbook As New HSSFWorkbook()
Dim sheetOne As HSSFSheet = hssfworkbook.CreateSheet("Sheet1")
hssfworkbook.CreateSheet("Sheet2")
hssfworkbook.CreateSheet("Sheet3")
Dim BoldFont As HSSFFont = hssfworkbook.CreateFont()
BoldFont.Boldweight = HSSFFont.BOLDWEIGHT_BOLD
Dim NormalFont As HSSFFont = hssfworkbook.CreateFont()
NormalFont.Boldweight = HSSFFont.BOLDWEIGHT_NORMAL
Dim cellStyleBold As HSSFCellStyle = hssfworkbook.CreateCellStyle()
With cellStyleBold
.setFont(BoldFont)
.Alignment = HSSFCellStyle.ALIGN_CENTER
End With
Dim cellStyleNormal As HSSFCellStyle = hssfworkbook.CreateCellStyle()
With cellStyleNormal
.setFont(NormalFont)
.Alignment = HSSFCellStyle.ALIGN_CENTER
End With
For i - 0 To 9 Step 1
If i Mod 2 = 0 Then
With Sheet1.CreateRow(i).CreateCell(1)
.SetCellValue(i)
.cellStyle = cellStyleBold
End With
Else
With Sheet1.CreateRow(i).CreateCell(1)
.SetCellValue(i)
.cellStyle = cellStyleNormal
End With
End If
Next

Resources