I have expanded on the above.
The new code allows you to enter the number of rows to be calculated. It also makes the end total column and the bottom total row to be read only. As it stands the computations are all addition, but this is easily changed in the code to *, /, or -.
Code: Select all
'=========================================================
' NumericEntryIntoGridOfTextboxes_Dev06.bas
' Author: RNBW
' 7 October 2018
'---------------------------------------------------------------------------------
'INSTRUCTIONS:
'Enter any text you want in col 2, rows 2 & 3. It is superfluous to the exercise and is only
'included for my own future use.
'Enter numbers into columns 3 and 4 in rows 2 and 3. They will be automatically
'checked for numeric validity in the range 0 to 9, minus and period and for only one
'inclusion of minus and period and ensuring that the minus only occurs as the first
'character.
'The final display presents the numbers to 3 decimal places
'=========================================================
#Include "WinGUI.bi"
#include "string.bi"
Dim Shared As Long NumOfRows = 10 'this is an arbitrary value, it doesn't seem to matter
dim shared as long NumOfCols = 5
Dim Shared As String sRows, sCols
Dim Shared As HWND Window_Main, Static_Text, Label_a, Edit_a, Button_Num, Button_CloseGrid, Label_b
Dim Shared As MSG msg
Dim Shared As String text, text2
Dim Shared As HWND Edit_Text(1 To NumOfRows, 1 To NumOfCols)
Dim Shared As HWND Button_Calc
Dim Shared As Long vPos, hPos, bWidth, bHeight, row, col
DIM Shared AS STRING sTxt, oldsTxt
DIM Shared AS INTEGER pos0
DIM Shared AS DOUBLE numb(2 TO NumOfRows, 3 TO NumOfCols)
DIM Shared AS DOUBLE totalRows(2 TO NumOfRows, NumOfCols)
DIM Shared AS DOUBLE totalCols(NumOfRows, 3 TO NumOfCols)
dim shared as double number
FUNCTION sNum(BYVAL sTxt AS STRING) AS STRING
'Function to check that character input is 0-9, - or .
DIM AS STRING sNum1
DIM AS INTEGER i, a, t
FOR i = 1 TO LEN(sTxt)
a = ASC(MID(sTxt,i,1))
IF a = 46 THEN t = t + 1
IF (a = 46) AND (t > 1) THEN a = 0 'only DOT after FIRST is cleared
IF a = 45 AND i>1 THEN a = 0 'so really almost anything do, not just 8
'IF a = 46 AND i = 1 THEN sNum1 = "0" + sNum1
IF a = 45 OR a = 46 OR a > 47 AND a < 58 THEN sNum1 = sNum1 + CHR(a)
NEXT
'a=ASC(MID(sTxt,1,1))
'IF a = 45 AND MID(sTxt,2,1) = "." THEN sNum1 = "-0" + sNum1
RETURN sNum1
END FUNCTION
'---------------------
' MAIN WINDOW
'---------------------
Sub OpenWindow_Main()
Window_Main = Window_New(100, 100, 750, 400, "Numeric Input Into A Grid of Textboxes")
End Sub
OpenWindow_Main()
' Gadgets to state number of rows
'sub identifyGrid(NumOfRows)
Label_a = Label_New(10,10,270,20,"How many rows do you want to calculate",, Window_Main)
Edit_a = EditBox_New(300,10,30,20,"", ES_CENTER or WS_BORDER, Window_Main)
Button_Num = Button_New(350,10,100,20, "Enter",, Window_Main)
'end sub
'sub resizeGrid(NumOfRows)
Label_b = Label_New(10,40,350,20,"To resize the grid FIRST click resize button",, Window_Main)
Button_CloseGrid = Button_New(350,40,100,20, "Resize Grid",, Window_Main)
'end sub
'Open console
'Screen 12
'open cons for output as #1
Button_Calc = Button_New(10, 60, 100, 20, "Calculate!",, Window_Main)
'-------------------------------
' SET UP THE GRID
'-------------------------------
sub setUpGrid(NumOfRows as long)
reDim As HWND Edit_Text(1 To NumOfRows, 1 To NumOfCols)
reDIM AS DOUBLE numb(2 TO NumOfRows, 3 TO NumOfCols)
reDIM AS DOUBLE totalRows(2 TO NumOfRows, NumOfCols)
reDIM AS DOUBLE totalCols(NumOfRows, 3 TO NumOfCols)
Dim ES_x as Integer
vPos = 90: bHeight = 20
For row = 1 To NumOfRows-1
For col = 1 To 5
ES_x=ES_LEFT ' ## default left justified ##
select Case col
Case 1
hPos = 10: bWidth = 65: ES_x=ES_LEFT
Case 2
hPos = 75: bWidth = 380: ES_x=ES_LEFT
CASE 3 TO 4
hpos = col*65+(455-65*3) : bWidth = 65: ES_x = ES_RIGHT 'right justify
CASE 5
hPos = (10+65+380)+(col-3)*65 : bWidth = 75: ES_x = ES_RIGHT or ES_READONLY 'right justify
End Select
Edit_Text(row, col) = EditBox_New(hPos, vPos+bHeight*(row-1), bWidth+1, bHeight+1, "",ES_x, Window_Main)
Next
Next
' This is a bit clumsy but is the best I could come up with
' It takes the last row of the grid which includes the column totals
' and makes them READONLY.
For row = NumOfRows To NumOfRows
For col = 1 To 5
ES_x=ES_LEFT ' ## default left justified ##
select Case col
Case 1
hPos = 10: bWidth = 65: ES_x=ES_LEFT or ES_READONLY
Case 2
hPos = 75: bWidth = 380 : ES_x=ES_LEFT or ES_READONLY
CASE 3 TO 4
hpos = col*65+(455-65*3) : bWidth = 65: ES_x = ES_RIGHT or ES_READONLY 'right justify
CASE 5
hPos = (10+65+380)+(col-3)*65 : bWidth = 75: ES_x = ES_RIGHT or ES_READONLY 'right justify
End Select
Edit_Text(row, col) = EditBox_New(hPos, vPos+bHeight*(row-1), bWidth+1, bHeight+1, "",ES_x, Window_Main)
Next
Next
'-----------------------------------
' SET UP HEADINGS IN ROW 1
'-----------------------------------
row = 1
For col = 3 To NumOfCols
EditBox_SetText(Edit_Text(row,col), "Number" + Str(col-2))
Next
EditBox_SetText(Edit_Text(row,2), "Description")
EditBox_SetText(Edit_Text(row,5), "TOTAL")
'----------------------------------
' SET UP HEADINGS IN COL 1
'----------------------------------
col = 1
For row = 2 To NumOfRows -1
For col = 1 To 1
EditBox_SetText(Edit_Text(row,col), "Row" + Str(row-1))
Next
Next
EditBox_SetText(Edit_Text(numOfRows,1), "TOTAL")
end sub
'Set timer to 300 miliseconds:
SETTIMER(Window_Main, 0, 300, 0 )
DO
WaitEvent(Window_Main,msg)
SELECT CASE msg.message
' CASE WM_LBUTTONDOWN
'SELECT CASE msg.message
CASE WM_TIMER
'Check contents of the edit box every 300 millisecinds
For row = 2 to NumOfRows
FOR col = 3 TO 4
sTxt = EditBox_GetText(Edit_Text(row,col)) 'get text from edit box
oldsTxt = sTxt 'make text the oldtext
sTxt = sNum(sTxt) 'gets new text from function sNum(sTxt) which does the checking
IF oldsTxt <> sTxt THEN
EditBox_SetText(Edit_Text(row,col), sTxt) 'if old text is not the same as the new text then use new text
pos0 = LEN(sTxt) 'position of character is the length of the current text
SENDMESSAGE(Edit_Text(row,col), EM_SETSEL, pos0, pos0)
END IF
NEXT col
NEXT row
CASE WM_LBUTTONDOWN
if msg.hwnd = Button_Num then
text = EditBox_GetText(Edit_a)
NumOfRows = val(text)
NumOfRows = NumOfRows + 2
setUpGrid(NumOfRows)
SendMessage(Edit_a, WM_CLOSE, 0, 0)
print NumOfRows
Else
' Click Close Grid button to close grid
if msg.hwnd = Button_CloseGrid THEN
for row = 1 to NumOfRows
for col = 1 to 5
DestroyWindow(Edit_Text(row,col))
next
Next
Edit_a = EditBox_New(300,10,30,20,"", ES_CENTER or WS_BORDER, Window_Main)
Else
'If Calculate! button is clicked then carry out calculation
IF msg.hwnd = Button_Calc THEN
totalCols(NumOfRows,col) = 0
FOR row = 2 to NumOfRows
FOR col = 3 TO 5
' Total Rows--->
sTxt = EditBox_GetText(Edit_Text(row,col))
numb(row,col) = VAL(sTxt)
sTxt = format(numb(row,col), "###0.000")
EditBox_SetText(Edit_Text(row,col), sTxt)
totalRows(row,5) = numb(row, 3) + numb(row,4)
sTxt = format(totalRows(row,5), "####0.000")
EditBox_SetText(Edit_Text(row,5), sTxt)
'Total Columns--->
sTxt = EditBox_GetText(Edit_Text(row,col))
numb(row,col) = val(sTxt)
totalCols(NumOfRows,col) = totalCols(NumOfRows,col) + numb(row-1,col)
sTxt = format(totalCols(NumOfRows,col), "####0.000")
EditBox_SetText(Edit_Text(NumOfRows,col), sTxt)
print row; " "; col; " "; numb(row,col)
NEXT
NEXT
end if
END IF
End if
END SELECT
LOOP UNTIL Window_Event_Close(Window_Main, msg)
End
I think the code shows what can be done with simple code. However, I am looking to use sub-editing, which I am working on at present.
I hope the code is useful and gives users ideas on how they can utilise it for their own purposes. it would be nice to see examples posted.