Setting up a table with varying numbers of rows
Setting up a table with varying numbers of rows
I want to set up a small spreadsheet-like table, 7 columns wide (with varying widths) and up to 8 rows deep. The number of rows to be displayed will be input by the user before they are displayed on the screen. This figure could be anything between 1 and 8. So when displayed, the table would be anything between 1 row and 7 columns to 8 rows and 7 columns.
Data will be entered into the cells by the user which can then be read as variables and used in various formulae.
How would I go about this in Purebasic?
Data will be entered into the cells by the user which can then be read as variables and used in various formulae.
How would I go about this in Purebasic?
Re: Setting up a table with varying numbers of rows
a 2D string array?
you can also change the size of an array while preserving its contents using ReDim()
Code: Select all
NumRows = 8
NumCols = 8
Dim MyArray.s(NumCols,NumRows)
;Fill the MyArray array with some values
For col = 1 To 8
For row = 1 To 8
MyArray(col,row) = "Col"+Str(col) + ",Row"+Str(row)
Next row
Next col
Re: Setting up a table with varying numbers of rows
Hi Keya
Thanks for the quick reply.
It's not the array part that's the difficulty. Maybe I need to explain myself better. What I want to do is to display a table in the form of boxes (like a spreadsheet) which can vary between 1 row / 7 columns and 8 rows / 7 columns. The user will decide how many rows immediately before displaying the mini-spreadsheet. It's how you achieve this that I need to know.
I originally did this in LB Booster (Liberty Basic) using a loop to set up the table (the concept code was kindly produced by Richard Russell and I modified it to meet my requirements. I want to be able to do something similar in Purebasic but I can't work out how to do it.
Thanks for the quick reply.
It's not the array part that's the difficulty. Maybe I need to explain myself better. What I want to do is to display a table in the form of boxes (like a spreadsheet) which can vary between 1 row / 7 columns and 8 rows / 7 columns. The user will decide how many rows immediately before displaying the mini-spreadsheet. It's how you achieve this that I need to know.
I originally did this in LB Booster (Liberty Basic) using a loop to set up the table (the concept code was kindly produced by Richard Russell and I modified it to meet my requirements. I want to be able to do something similar in Purebasic but I can't work out how to do it.
Re: Setting up a table with varying numbers of rows
Hi,
maybe something like that:
Bernd
maybe something like that:
Code: Select all
OpenWindow(0, 0, 0, 800, 600, "Runtime ListIconGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(0, 10, 10, 50, 20, "Rows:")
SpinGadget(1, 70, 10, 50, 20, 1, 10, #PB_Spin_ReadOnly|#PB_Spin_Numeric)
SetGadgetState(1, 1)
ButtonGadget(2, 130, 10, 30, 20, "Set")
ListIconGadget(3, 10, 40, 780, 550, "1", 80)
Columns = 1
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
Case 2
If IsGadget(3)
NewColumns = GetGadgetState(1)
If NewColumns > Columns
For i = Columns To NewColumns
AddGadgetColumn(3, i, Str(i + 1), 80)
Next i
Columns = NewColumns
ElseIf NewColumns < Columns
For i = Columns To NewColumns Step -1
RemoveGadgetColumn(3, i)
Next i
EndIf
EndIf
EndSelect
Case #PB_Event_CloseWindow
Exit = #True
EndSelect
Until Exit
Re: Setting up a table with varying numbers of rows
Hi Bernd
Thank you for your response, it was an interesting bit of code, because I've not done much with listboxes yet. Unfortunately, not what I am looking for.
If you imagine a spreadsheet made up of textboxes, with 7 columns of various widths and with rows between 1 and 8 (the number of rows being chosen by the user at runtime. That's what I'm trying to achieve.
I'm working on it and managed to get a single column of textboxes, but it seems to be a bit of a bodge and I think there must be a better way.
The code I've used is shown below (it's in a vary rough state as I've just been playing with it but it should give an idea of what I'm after.
What I have found is that if you remove the -1 in gNum = x-1 and the +1 in StringGadget(gNum+x, .... then a column is of textboxes is printed out, but one textbox is missing.
I have still to start with more than one column, but any help is appreciated.
Best regards
Ray
Thank you for your response, it was an interesting bit of code, because I've not done much with listboxes yet. Unfortunately, not what I am looking for.
If you imagine a spreadsheet made up of textboxes, with 7 columns of various widths and with rows between 1 and 8 (the number of rows being chosen by the user at runtime. That's what I'm trying to achieve.
I'm working on it and managed to get a single column of textboxes, but it seems to be a bit of a bodge and I think there must be a better way.
The code I've used is shown below (it's in a vary rough state as I've just been playing with it but it should give an idea of what I'm after.
Code: Select all
;produces a single column of textboxes
#WindowWidth = 390
#WindowHeight = 350
If OpenWindow(0, 100, 200, #WindowWidth, #WindowHeight, "PureBasic - Gadget Demonstration", #PB_Window_MinimizeGadget)
Top = 10
gHt = 24
gNum.i
FrameGadget(#PB_Any, 10, Top, 370, 290, "Player...") : Top+20
For x = 1 To 6
gNum = x-1
StringGadget(gNum+x, 20, Top, 200, gHt, "")
Debug gNum
Top = Top+gHt
Next
ButtonGadget(2, 295, Top+gHt*4, 72, gHt, "Useless") : Top+35
; the following is just a bit of useless code
Repeat
Event.l = WaitWindowEvent()
Select Event
Case 1 ; dummy selection
EndSelect
Until Event = #PB_Event_CloseWindow Or Quit = #True
EndIf
I have still to start with more than one column, but any help is appreciated.
Best regards
Ray
Re: Setting up a table with varying numbers of rows
That is because one of the string gadgets will have a gadget# equal to 2. The button gadget then overwrites it (since it uses the same gadget#) and thus destroys the relevant string gadget. You need to think more carefully about the gadget#'s and make sure that none are repeated.
The following might get you started.
The following might get you started.
Code: Select all
;produces a single column of textboxes
#WindowWidth = 840
#WindowHeight = 350
If OpenWindow(0, 100, 200, #WindowWidth, #WindowHeight, "PureBasic - Gadget Demonstration", #PB_Window_MinimizeGadget)
For row=0 To 6
For col = 0 To 7
StringGadget(row*8+col, 20 + col*100, 10 + row*24, 100, 24, "")
Next
Next
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Debug "Event fired on Gadget : " + Str(EventGadget())
EndSelect
Until Event = #PB_Event_CloseWindow Or Quit = #True
EndIf
I may look like a mule, but I'm not a complete ass.
Re: Setting up a table with varying numbers of rows
Thanks
What you have produced is on the way to what I am looking for. I'll have a close look at your explanation and at your code and see if I can modify it to what I am looking for.
Ray
What you have produced is on the way to what I am looking for. I'll have a close look at your explanation and at your code and see if I can modify it to what I am looking for.
Ray
-
- User
- Posts: 43
- Joined: Thu Nov 27, 2014 3:10 pm
- Location: San Juan, Puerto Rico
Re: Setting up a table with varying numbers of rows
@RNBW
Hope this helps you.
Hope this helps you.

Code: Select all
;{ ==Code Header Comment==============================
; Name/title: StringGadgetsSpreadsheet.pb
; Executable name: StringGadgetsSpreadsheet.exe
; Version: 1.0
; Author: Amílcar Matos Pérez
; Collaborators: Based on Srod concept.
; Translation by:
; Create date: 05/Feb/2016
; Previous releases:
; This Release Date:
; Operating system: Windows [X]GUI
; Compiler version: PureBasic 5.41 (x64)
; Copyright: (C)2015 AMP All rights reserved.
; License: Free to use. Author credit kindly requested. All common disclaimers apply.
; Libraries:
; English Forum: http://www.purebasic.fr/english/viewtopic.php?f=13&t=64765
; French Forum:
; German Forum:
; Tested platforms: Windows
; Description: To create a table of string gadgets as defined by the user.
; Advertising: Honest, dependable, on time coding help for your commercial projects,
; please send a private message to Amílcar Matos Pérez in the PureBasic forum.
; ====================================================
;.......10........20........30........40........50........60........70........80
;}
EnableExplicit
;{ Constants
#WindowWidth = 840
#WindowHeight = 350
#CellWidth = 100
#CellHeight = 24
#XMargin = 20
#YMargin = 10
#MaxNbOfRows = 8
#MaxNbOfColumns = 7
#MinNbOfRows = 1 ; minimum number of rows.
#MinNbOfColumns = 1 ; minimum number of columns.
;}
;{ constants control - raise a debugging warning for any true condition.
If #MinNbOfRows > #MaxNbOfRows
MessageRequester ("Info", "Minimum number of rows exceed the maximum number allowed.", #MB_ICONQUESTION)
End
EndIf
If #MinNbOfColumns > #MaxNbOfColumns
MessageRequester ("Info", "Minimum number of columns exceed the maximum number allowed.", #MB_ICONQUESTION)
End
EndIf
;}
;{ Variable exposure
Global Dim AllTableGadgetNbs(0)
Global GoBtn.l
Global NewCols.l
Global NewRows.l
Global SpinCols.l
Global SpinRows.l
Global Flags.l
Global Title$
Global Event.l
Global Quit.l
;}
Declare.l Caribbean_Window_Events(Event)
Declare.l StringGadgetsTableMaker(MaxRows, MaxCols, Array AllTableGadgetNbs(1))
Declare.l GadgetsEraser(Array AllTableGadgetNbs(1))
;{ Main program.
Flags = #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered
Title$ = "Playing with string gadgets on a nice caribbean day."
If OpenWindow(0, 0, 0, #WindowWidth, #WindowHeight, Title$, Flags)
StringGadgetsTableMaker(#MaxNbOfRows, #MaxNbOfColumns, AllTableGadgetNbs())
TextGadget (#PB_Any, 730, 24, 50, 20, "Rows:")
TextGadget (#PB_Any, 730, 48, 50, 20, "Cols:")
Flags = #PB_Spin_ReadOnly|#PB_Spin_Numeric
SpinRows = SpinGadget (#PB_Any, 770, 24, 50, 20, 1, 8, Flags)
SpinCols = SpinGadget (#PB_Any, 770, 48, 50, 20, 1, 7, Flags)
GoBtn = ButtonGadget(#PB_Any, 770, 74, 30, 30, "Go")
Repeat
Event = WaitWindowEvent()
Quit = Caribbean_Window_Events(Event)
Until Quit = 0
EndIf
; All the opened windows are closed automatically by PureBasic.
End
;}
Procedure.l Caribbean_Window_Events(Event)
Select Event
Case #PB_Event_CloseWindow
ProcedureReturn #False
Case #PB_Event_Gadget
Select EventGadget()
Case SpinRows
Case SpinCols
Case GoBtn
; erase previous table.
GadgetsEraser(AllTableGadgetNbs())
; Get new row and column values. Assign minimum values if needed.
NewRows = GetGadgetState(SpinRows)
If NewRows < #MinNbOfRows Or
NewRows > #MaxNbOfRows
; minimum number of rows
NewRows = #MinNbOfRows
EndIf
NewCols = GetGadgetState(SpinCols)
If NewCols < #MinNbOfColumns Or
NewCols > #MaxNbOfColumns
; minimum number of colums
NewCols = #MinNbOfColumns
EndIf
; Build new table.
StringGadgetsTableMaker(NewRows, NewCols, AllTableGadgetNbs())
Default
; Other events.
Debug "Event fired on Gadget : " + Str(EventGadget())
EndSelect
EndSelect
ProcedureReturn #True
EndProcedure
Procedure.l StringGadgetsTableMaker(MaxRows, MaxCols, Array AllTableGadgetNbs(1))
; To build a new table.
;{ Protected variables
Protected ArrayRowNb.l
Protected CellGadgetNb.l
Protected GadgetPosX.l
Protected GadgetPosY.l
Protected Row.l
Protected Col.l
;}
; Test incoming values.
If MaxRows < 0 Or
MaxCols < 0
ProcedureReturn #False
EndIf
ReDim AllTableGadgetNbs(MaxRows * MaxCols)
For Row = 0 To MaxRows - 1 ; less one because count starts at zero.
For Col = 0 To MaxCols - 1
GadgetPosX = #XMargin + (Col * #CellWidth )
GadgetPosY = #YMargin + (Row * #CellHeight)
CellGadgetNb = StringGadget(#PB_Any, GadgetPosX , GadgetPosY, #CellWidth, #CellHeight, #Empty$)
ArrayRowNb = (Row * MaxCols) + Col
AllTableGadgetNbs(ArrayRowNb) = CellGadgetNb
If Row = 0
; Put a letter in the heading row. Letter starts with 'A'.
SetGadgetText(CellGadgetNb, Chr('A' + Col)) ;<= newbies look here; a purebasic self documenting no magic numbers trick!
EndIf
Next Col
If Row > 0
; Put a number on the first box of each row. Number starts at one.
ArrayRowNb = (Row * MaxCols) + 0 ;<= this formula is different from the above.
CellGadgetNb = AllTableGadgetNbs(ArrayRowNb)
SetGadgetText(CellGadgetNb, Str(Row))
EndIf
Next Row
ProcedureReturn #True
EndProcedure
Procedure.l GadgetsEraser(Array AllTableGadgetNbs(1))
; To erase screen gadgets.
;{ Protected variables
Protected GadgetNb.l
Protected MaxRows.l
Protected Row.l
;}
MaxRows = ArraySize(AllTableGadgetNbs())
For Row = 0 To MaxRows - 1 ;zero based counting.
; Get each gadget number from the array.
GadgetNb = AllTableGadgetNbs(Row)
; Erase each string gadget.
FreeGadget(GadgetNb)
Next Row
; Erase the old gadget number list.
ReDim AllTableGadgetNbs(0)
ProcedureReturn #True
EndProcedure
Re: Setting up a table with varying numbers of rows
Here's a simple text grid to illustrate the implementation of your requirements. It uses string gadgets, so the cells are editable, laid out evenly to fit the given size. This could easily be modified to accommodate varying cell-widths, and even replaced with text-gadgets for read-only cells. The grid is encapsulated within a container gadget, allowing it to be moved easily. Two convenience functions have been included to set the cell values and row-visibility.RNBW wrote:I want to set up a small spreadsheet-like table, 7 columns wide (with varying widths) and up to 8 rows deep. The number of rows to be displayed will be input by the user before they are displayed on the screen....
Code: Select all
Enumeration
#MainWindow
#ToggleView
#MoveGrid
EndEnumeration
Dim myTextGrid(7, 6)
Procedure TextGrid(x, y, width, height, Array gridInfo(2))
Protected cellSpacing = 5
Protected rows = ArraySize(gridInfo(), 1)
Protected columns = ArraySize(gridInfo(), 2)
Protected cellX = cellSpacing, cellY = cellSpacing
Protected cellHeight = (height - (cellSpacing * (rows + 2))) / (rows + 1)
Protected cellWidth = (width - (cellSpacing * (columns + 2))) / (columns + 1)
gridID = ContainerGadget(#PB_Any, x , y, width, height, #PB_Container_Flat)
For row = 0 To rows
For column = 0 To columns
gridInfo(row, column) = StringGadget(#PB_Any, cellX, cellY, cellWidth, cellHeight,
"Cell " + Str(row) + ", " + Str(column),
#PB_Text_Center | #PB_String_BorderLess)
SetGadgetColor(gridInfo(row, column), #PB_Gadget_BackColor, #White)
cellX + (cellWidth + cellSpacing)
Next column
cellX = cellSpacing
cellY + (cellHeight + cellSpacing)
Next row
CloseGadgetList()
ProcedureReturn gridID
EndProcedure
Procedure ShowGridRows(row, state = #False)
Shared myTextGrid()
For column = 0 To ArraySize(myTextGrid(), 2)
HideGadget(myTextGrid(row, column), state)
Next column
EndProcedure
Procedure SetGrid(row, column, text.s, frontColour = 0, backColour = 16777215)
Shared myTextGrid()
SetGadgetText(myTextGrid(row, column), text)
SetGadgetColor(myTextGrid(row, column), #PB_Gadget_FrontColor, frontColour)
SetGadgetColor(myTextGrid(row, column), #PB_Gadget_BackColor, backColour)
EndProcedure
wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#MainWindow, #PB_Any, #PB_Any, 1000, 700, "Simple Text Grid", wFlags)
ButtonGadget(#ToggleView, 10, 650, 980, 40, "CLICK TO TOGGLE-VIEW LAST TWO ROWS")
ButtonGadget(#MoveGrid, 10, 600, 980, 40, "CLICK TO MOVE TEXT GRID")
myGrid = TextGrid(10, 10, 700, 400, myTextGrid())
SetGrid(0, 0, "Click cell to edit...")
SetGrid(0, 1, "Manually set...", RGB(255, 255, 0), RGB(255, 0, 0))
SetGrid(3, 3, "Another one...", RGB(0, 0, 255), RGB(0, 255, 255))
SetGrid(6, 5, "Me too!", RGB(0, 100, 0), RGB(0, 255, 0))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
appQuit = 1
Case #PB_Event_Gadget
Select EventGadget()
Case #MoveGrid
x = Random(300, 10)
y = Random(200, 10)
ResizeGadget(myGrid, x, y, #PB_Ignore, #PB_Ignore)
Case #ToggleView
If state
state = #False
Else
state = #True
EndIf
ShowGridRows(6, state)
ShowGridRows(7, state)
EndSelect
EndSelect
Until appQuit = 1

Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: Setting up a table with varying numbers of rows
Thank you very much srod, Amilcar Matos and TI-994A for the code that you have provided. You have all given me ideas and code that I can put to use. I'll have a good look at your code and see how best to make use of it.
Thank you again!
Thank you again!
Re: Setting up a table with varying numbers of rows
Working on srod's solution first, I've modified it and produced code for a grid. It's worth noting the code line
Adding the 1 to width and rowHigh results in a much thinner line to the borders of the grid. I don't know why this happens and don't claim the idea to be mine. This work-around was provided by Richard Russell in LB Booster Conforums. I'm pleased to see it work in Purebasic as well.
The code for the grid is:
My next steps:
1.. Make the number of rows variable
2.. Make it possible to add text into boxes
3.. Make it possible to extract text from boxes
4.. Utilise the extracted text from boxes into variables for further use in the program
I know these seem pretty obvious but I am using it as a bit of a tutorial for myself.
I'm also going to look at the code provided by Amilcar Matos and TI-994A.
I'm still working on it!
Code: Select all
StringGadget(gNum, xpos, vpos+row*rowHigh-rowHigh, width+1, rowHigh+1, "")
The code for the grid is:
Code: Select all
[color=#00BF00];produces a grid of textboxes[/color]
#WindowWidth = 900
#WindowHeight = 350
If OpenWindow(0, 100, 200, #WindowWidth, #WindowHeight, "PureBasic - Grid Demonstration", #PB_Window_MinimizeGadget)
TotalRows = 12
vpos = 50 : rowHigh = 20
lDist.i = 30
For row = 1 To TotalRows
For col = 1 To 8
Select col
[color=#00BF00];First column[/color]
Case 1
xpos = lDist : width = 65
[color=#00BF00] ;Second Column[/color]
Case 2
xpos = lDist+65 : width = 380
[color=#00BF00];Columns 3 To 8[/color]
Case 3,4,5,6,7,8
xpos = lDist+col*65+(445-65*3) : width = 65
EndSelect
gNum.i = row*8-8+col
[color=#00BF00]; NOTE: add 1 to both width and rowHigh and this removes the duplication
; of the border of boxes, resulting in a thinner line.[/color]
StringGadget(gNum, xpos, vpos+row*rowHigh-rowHigh, width+1, rowHigh+1, "")
Debug gNum
Next col
Next row
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Debug "Event fired on Gadget : " + Str(EventGadget())
EndSelect
Until Event = #PB_Event_CloseWindow Or Quit = #True
EndIf
1.. Make the number of rows variable
2.. Make it possible to add text into boxes
3.. Make it possible to extract text from boxes
4.. Utilise the extracted text from boxes into variables for further use in the program
I know these seem pretty obvious but I am using it as a bit of a tutorial for myself.
I'm also going to look at the code provided by Amilcar Matos and TI-994A.
I'm still working on it!
Re: Setting up a table with varying numbers of rows
I've just looked at my last posting.
A bit disappointing, I was hoping that the comments would show up in green.
A bit disappointing, I was hoping that the comments would show up in green.
Re: Setting up a table with varying numbers of rows
It is no mystery.
The 'borders' of the grid are simply the borders of the string gadgets. By using the +1 you are effectively overlapping the gadgets which means the bottom border of one gadget overlaps the top border of the gadget below it and so on.
The 'borders' of the grid are simply the borders of the string gadgets. By using the +1 you are effectively overlapping the gadgets which means the bottom border of one gadget overlaps the top border of the gadget below it and so on.
I may look like a mule, but I'm not a complete ass.
Re: Setting up a table with varying numbers of rows
Colour tags work only in normal text blocks...RNBW wrote:...I was hoping that the comments would show up in green.
Code: Select all
[color=#00BF00]...but are ignored in code blocks[/color]

Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel 

Re: Setting up a table with varying numbers of rows
srod
You are correct with your explanation of why the "+1" trick works. The effect is not noticeable except for making the grid lines thinner. If instead you use, say, "+10" (obviously you wouldn't) then you can see the effect on the last row and last column which become larger by this amount.
If you want to have a small space between the textboxes in the grid, then use "-1" or "-2". It's a neat solution.
However, my reason for mentioning it was because none of the contributors had used it and not many, in my experience are aware of it (that is in various computer languages). It's a handy tip and can make a grid look a lot smarter (much more like a spreadsheet).
Anyway, thanks again for the code you produced. It showed I wasn't too far away with the code I had written for LB Booster, but I was not aware how to convert it to Purebasic.
Ray
You are correct with your explanation of why the "+1" trick works. The effect is not noticeable except for making the grid lines thinner. If instead you use, say, "+10" (obviously you wouldn't) then you can see the effect on the last row and last column which become larger by this amount.
If you want to have a small space between the textboxes in the grid, then use "-1" or "-2". It's a neat solution.
However, my reason for mentioning it was because none of the contributors had used it and not many, in my experience are aware of it (that is in various computer languages). It's a handy tip and can make a grid look a lot smarter (much more like a spreadsheet).
Anyway, thanks again for the code you produced. It showed I wasn't too far away with the code I had written for LB Booster, but I was not aware how to convert it to Purebasic.
Ray