Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
QB64PE Excel-type spreadsheet supporting formulas and QB64PE macros?
#6
Code: (Select All)

Option _Explicit

' ============================================================
' MiniSheet GUI 10x10 for QB64PE
' Clickable cells, in-place editing, simple formulas:
'  =A1 + D5*3
' Supports + - * / and parentheses.
' Text is allowed but treated as 0 in calculations.
' No formatting features (fonts/borders options/etc.).
' ============================================================

Const RMAX% = 10
Const CMAX% = 10

' --- UI layout (pixels) ---
Const WINW% = 980
Const WINH% = 420
Const X0% = 70 ' grid origin x (top-left of cell A1)
Const Y0% = 60 ' grid origin y
Const CELLW% = 85
Const CELLH% = 28
Const HDRH% = 24 ' header height area
Const HDRW% = 50 ' header width area
Const EDITY% = 360 ' editor/status line y

Dim Shared cellIn$(RMAX%, CMAX%)
Dim Shared cellVal!(RMAX%, CMAX%)
Dim Shared state%(RMAX%, CMAX%)
Dim Shared laster$

Dim Shared selR%, selC%
Dim Shared editing%
Dim Shared editText$
Dim Shared prevMouse1%
Dim Shared quit%


Screen _NewImage(WINW%, WINH%, 32)
_Title "MiniSheet GUI (QB64PE) - Click cells, type values/formulas"

InitGrid
MainLoop
End

'init
Sub InitGrid
    Dim r%, c%

    laster$ = ""
    For r% = 1 To RMAX%
        For c% = 1 To CMAX%
            cellIn$(r%, c%) = ""
            cellVal!(r%, c%) = 0!
            state%(r%, c%) = 0
        Next c%
    Next r%

    selR% = 1
    selC% = 1
    editing% = 0
    editText$ = ""
    prevMouse1% = 0
    quit% = 0
End Sub


Sub MainLoop
    Do While quit% = 0
        _Limit 60

        HandleMouse
        HandleKeys
        DrawUI
    Loop
End Sub


Sub HandleMouse
    Dim mx%, my%, m1%
    Dim r%, c%

    Do While _MouseInput
        mx% = _MouseX
        my% = _MouseY
        m1% = _MouseButton(1)

        ' Detect left-click rising edge
        If m1% <> 0 And prevMouse1% = 0 Then
            If InGrid%(mx%, my%) Then
                MouseToCell mx%, my%, r%, c%
                selR% = r%
                selC% = c%

                ' Start editing on click
                editing% = -1
                editText$ = cellIn$(selR%, selC%)
            End If
        End If

        prevMouse1% = m1%
    Loop
End Sub

Function InGrid% (mx%, my%)
    Dim gx1%, gy1%, gx2%, gy2%

    gx1% = X0%
    gy1% = Y0%
    gx2% = X0% + CMAX% * CELLW%
    gy2% = Y0% + RMAX% * CELLH%

    If mx% >= gx1% And mx% < gx2% And my% >= gy1% And my% < gy2% Then
        InGrid% = -1
    Else
        InGrid% = 0
    End If
End Function

Sub MouseToCell (mx%, my%, r%, c%)
    Dim dx%, dy%

    dx% = mx% - X0%
    dy% = my% - Y0%

    c% = (dx% \ CELLW%) + 1
    r% = (dy% \ CELLH%) + 1

    If c% < 1 Then c% = 1
    If c% > CMAX% Then c% = CMAX%
    If r% < 1 Then r% = 1
    If r% > RMAX% Then r% = RMAX%
End Sub

'keyboard
Sub HandleKeys
    Dim k%
    Dim ch$
    Dim raw$

    k% = _KeyHit
    If k% = 0 Then Exit Sub

    If editing% <> 0 Then
        ' Editing mode: build editText$
        If k% = 27 Then
            ' ESC cancels edit
            editing% = 0
            editText$ = ""
            Exit Sub
        End If

        If k% = 13 Then
            ' ENTER commits
            raw$ = TrimAll$(editText$)
            cellIn$(selR%, selC%) = Unquote$(raw$)
            editing% = 0
            editText$ = ""
            Exit Sub
        End If

        If k% = 8 Then
            ' BACKSPACE
            If Len(editText$) > 0 Then editText$ = Left$(editText$, Len(editText$) - 1)
            Exit Sub
        End If

        ' Printable ASCII only (basic)
        If k% >= 32 And k% <= 126 Then
            ch$ = Chr$(k%)
            editText$ = editText$ + ch$
        End If

    Else
        ' Not editing: ESC quits
        If k% = 27 Then quit% = -1
    End If
End Sub



'ui
Sub DrawUI
    Cls
    DrawHeaders
    DrawGrid
    DrawEditor
    _Display
End Sub

Sub DrawHeaders
    Dim c%, r%
    Dim x%, y%
    Dim s$

    ' Column letters
    For c% = 1 To CMAX%
        x% = X0% + (c% - 1) * CELLW% + 6
        y% = Y0% - HDRH%
        s$ = ColToLetter$(c%)
        _PrintString (x%, y%), s$
    Next c%

    ' Row numbers
    For r% = 1 To RMAX%
        x% = X0% - HDRW%
        y% = Y0% + (r% - 1) * CELLH% + 6
        s$ = LTrim$(Str$(r%))
        _PrintString (x%, y%), s$
    Next r%
End Sub

Sub DrawGrid
    Dim r%, c%
    Dim x1%, y1%, x2%, y2%
    Dim raw$, show$
    Dim v!
    Dim wChars%

    laster$ = ""
    ClearStates

    ' Simple grid lines
    For c% = 0 To CMAX%
        x1% = X0% + c% * CELLW%
        y1% = Y0%
        x2% = x1%
        y2% = Y0% + RMAX% * CELLH%
        Line (x1%, y1%)-(x2%, y2%), _RGB32(120, 120, 120)
    Next c%

    For r% = 0 To RMAX%
        x1% = X0%
        y1% = Y0% + r% * CELLH%
        x2% = X0% + CMAX% * CELLW%
        y2% = y1%
        Line (x1%, y1%)-(x2%, y2%), _RGB32(120, 120, 120)
    Next r%

    ' Selected cell highlight (just a soft fill so you see where you are)
    x1% = X0% + (selC% - 1) * CELLW% + 1
    y1% = Y0% + (selR% - 1) * CELLH% + 1
    x2% = x1% + CELLW% - 2
    y2% = y1% + CELLH% - 2
    Line (x1%, y1%)-(x2%, y2%), _RGB32(220, 235, 255), BF

    ' Cell contents
    wChars% = 10 ' rough truncation count for default font
    For r% = 1 To RMAX%
        For c% = 1 To CMAX%
            raw$ = TrimAll$(cellIn$(r%, c%))
            show$ = ""

            If raw$ <> "" Then
                If Left$(raw$, 1) = "=" Then
                    v! = EvalCell!(r%, c%)
                    show$ = LTrim$(Str$(v!))
                ElseIf IsPlainNumber%(raw$) Then
                    show$ = raw$
                Else
                    ' text
                    show$ = raw$
                End If
            End If

            If Len(show$) > wChars% Then show$ = Left$(show$, wChars%)

            x1% = X0% + (c% - 1) * CELLW% + 4
            y1% = Y0% + (r% - 1) * CELLH% + 6
            _PrintString (x1%, y1%), show$
        Next c%
    Next r%
End Sub

Sub DrawEditor
    Dim s1$, s2$, s3$

    s1$ = "Selected: " + CellName$(selR%, selC%)
    s2$ = "Click a cell to edit. Enter=commit, Esc=cancel. Esc (when not editing)=quit."
    s3$ = "Input: "

    _PrintString (20, EDITY% - 26), s1$
    _PrintString (20, EDITY% - 10), s2$

    If editing% <> 0 Then
        _PrintString (20, EDITY% + 10), s3$ + editText$
    Else
        _PrintString (20, EDITY% + 10), s3$ + cellIn$(selR%, selC%)
    End If

    If laster$ <> "" Then
        _PrintString (20, EDITY% + 30), "Note: " + laster$
    End If
End Sub

Sub ClearStates
    Dim r%, c%

    For r% = 1 To RMAX%
        For c% = 1 To CMAX%
            state%(r%, c%) = 0
        Next c%
    Next r%
End Sub


' Helpers
Function ColToLetter$ (c%)
    ColToLetter$ = Chr$(Asc("A") + c% - 1)
End Function

Function CellName$ (r%, c%)
    CellName$ = ColToLetter$(c%) + LTrim$(Str$(r%))
End Function

Function TrimAll$ (s$)
    TrimAll$ = LTrim$(RTrim$(s$))
End Function

Function Unquote$ (s$)
    Dim t$
    t$ = TrimAll$(s$)
    If Len(t$) >= 2 Then
        If Left$(t$, 1) = Chr$(34) And Right$(t$, 1) = Chr$(34) Then
            Unquote$ = Mid$(t$, 2, Len(t$) - 2)
            Exit Function
        End If
    End If
    Unquote$ = t$
End Function


' Evaluation / Parser
Function EvalCell! (r%, c%)
    Dim raw$, s$
    Dim idx%, er%
    Dim v!

    raw$ = TrimAll$(cellIn$(r%, c%))

    If state%(r%, c%) = 2 Then
        EvalCell! = cellVal!(r%, c%)
        Exit Function
    End If

    If state%(r%, c%) = 1 Then
        laster$ = "Cyclic reference detected. Returning 0 for cycle."
        EvalCell! = 0!
        Exit Function
    End If

    state%(r%, c%) = 1

    If raw$ = "" Then
        v! = 0!
    ElseIf Left$(raw$, 1) = "=" Then
        s$ = Mid$(raw$, 2)
        idx% = 1
        er% = 0
        v! = ParseExpr!(s$, idx%, er%)
        SkipSpaces s$, idx%
        If er% <> 0 Or idx% <= Len(s$) Then
            laster$ = "Formula eror in " + CellName$(r%, c%) + ". Returning 0."
            v! = 0!
        End If
    ElseIf IsPlainNumber%(raw$) Then
        idx% = 1
        er% = 0
        v! = ReadNumber!(raw$, idx%, er%)
        If er% <> 0 Then v! = 0!
    Else
        ' text counts as 0 in calculations
        v! = 0!
    End If

    cellVal!(r%, c%) = v!
    state%(r%, c%) = 2
    EvalCell! = v!
End Function

Function ParseExpr! (s$, idx%, er%)
    Dim v!, t!
    Dim op$

    v! = ParseTerm!(s$, idx%, er%)
    If er% <> 0 Then ParseExpr! = 0!: Exit Function

    Do
        SkipSpaces s$, idx%
        If idx% > Len(s$) Then Exit Do
        op$ = Mid$(s$, idx%, 1)
        If op$ <> "+" And op$ <> "-" Then Exit Do
        idx% = idx% + 1
        t! = ParseTerm!(s$, idx%, er%)
        If er% <> 0 Then ParseExpr! = 0!: Exit Function
        If op$ = "+" Then v! = v! + t! Else v! = v! - t!
    Loop

    ParseExpr! = v!
End Function

Function ParseTerm! (s$, idx%, er%)
    Dim v!, f!
    Dim op$

    v! = ParseFactor!(s$, idx%, er%)
    If er% <> 0 Then ParseTerm! = 0!: Exit Function

    Do
        SkipSpaces s$, idx%
        If idx% > Len(s$) Then Exit Do
        op$ = Mid$(s$, idx%, 1)
        If op$ <> "*" And op$ <> "/" Then Exit Do
        idx% = idx% + 1
        f! = ParseFactor!(s$, idx%, er%)
        If er% <> 0 Then ParseTerm! = 0!: Exit Function

        If op$ = "*" Then
            v! = v! * f!
        Else
            If f! = 0! Then
                laster$ = "Division by zero. Returning 0."
                v! = 0!
            Else
                v! = v! / f!
            End If
        End If
    Loop

    ParseTerm! = v!
End Function

Function ParseFactor! (s$, idx%, er%)
    Dim ch$, sign!, v!
    Dim cch$, col%, row%
    Dim cell$, start%

    SkipSpaces s$, idx%
    If idx% > Len(s$) Then er% = 1: ParseFactor! = 0!: Exit Function

    ch$ = Mid$(s$, idx%, 1)

    ' Unary +/-
    If ch$ = "+" Or ch$ = "-" Then
        If ch$ = "-" Then sign! = -1! Else sign! = 1!
        idx% = idx% + 1
        v! = ParseFactor!(s$, idx%, er%)
        ParseFactor! = sign! * v!
        Exit Function
    End If

    ' Parentheses
    If ch$ = "(" Then
        idx% = idx% + 1
        v! = ParseExpr!(s$, idx%, er%)
        SkipSpaces s$, idx%
        If idx% > Len(s$) Or Mid$(s$, idx%, 1) <> ")" Then
            er% = 1
            ParseFactor! = 0!
            Exit Function
        End If
        idx% = idx% + 1
        ParseFactor! = v!
        Exit Function
    End If

    ' Cell ref: A1..J10
    If IsAlpha%(ch$) Then
        start% = idx%
        idx% = idx% + 1
        Do While idx% <= Len(s$)
            cch$ = Mid$(s$, idx%, 1)
            If IsDigit%(cch$) = 0 Then Exit Do
            idx% = idx% + 1
        Loop
        cell$ = UCase$(Mid$(s$, start%, idx% - start%))
        If CellOK%(cell$, row%, col%) = 0 Then
            er% = 1
            ParseFactor! = 0!
            Exit Function
        End If
        ParseFactor! = EvalCell!(row%, col%)
        Exit Function
    End If

    ' Number
    v! = ReadNumber!(s$, idx%, er%)
    ParseFactor! = v!
End Function

Sub SkipSpaces (s$, idx%)
    Dim ch$

    Do While idx% <= Len(s$)
        ch$ = Mid$(s$, idx%, 1)
        If ch$ <> " " And ch$ <> Chr$(9) Then Exit Do
        idx% = idx% + 1
    Loop
End Sub

Function ReadNumber! (s$, idx%, er%)
    Dim start%, ch$, dotCount%, num$

    SkipSpaces s$, idx%
    If idx% > Len(s$) Then er% = 1: ReadNumber! = 0!: Exit Function

    start% = idx%
    dotCount% = 0

    Do While idx% <= Len(s$)
        ch$ = Mid$(s$, idx%, 1)
        If IsDigit%(ch$) Then
            idx% = idx% + 1
        ElseIf ch$ = "." Then
            dotCount% = dotCount% + 1
            If dotCount% > 1 Then Exit Do
            idx% = idx% + 1
        Else
            Exit Do
        End If
    Loop

    num$ = Mid$(s$, start%, idx% - start%)
    If num$ = "" Or num$ = "." Then
        er% = 1
        ReadNumber! = 0!
        Exit Function
    End If

    ReadNumber! = CSng(Val(num$))
End Function

Function IsPlainNumber% (s$)
    Dim idx%, er%
    Dim v!

    s$ = TrimAll$(s$)
    If s$ = "" Then IsPlainNumber% = 0: Exit Function

    idx% = 1
    er% = 0
    v! = ReadNumber!(s$, idx%, er%)
    SkipSpaces s$, idx%

    If er% <> 0 Then
        IsPlainNumber% = 0
    ElseIf idx% <= Len(s$) Then
        IsPlainNumber% = 0
    Else
        IsPlainNumber% = -1
    End If
End Function

Function IsAlpha% (ch$)
    Dim a%
    If ch$ = "" Then IsAlpha% = 0: Exit Function
    a% = Asc(UCase$(Left$(ch$, 1)))
    If a% >= Asc("A") And a% <= Asc("Z") Then IsAlpha% = -1 Else IsAlpha% = 0
End Function

Function IsDigit% (ch$)
    Dim a%
    If ch$ = "" Then IsDigit% = 0: Exit Function
    a% = Asc(Left$(ch$, 1))
    If a% >= Asc("0") And a% <= Asc("9") Then IsDigit% = -1 Else IsDigit% = 0
End Function

Function LetterToCol% (ch$)
    Dim a%
    ch$ = UCase$(ch$)
    a% = Asc(ch$)
    If a% < Asc("A") Or a% > Asc("Z") Then LetterToCol% = 0: Exit Function
    LetterToCol% = (a% - Asc("A")) + 1
End Function

Function CellOK% (cell$, r%, c%)
    Dim ch$, num$, i%, d$
    Dim rr%

    cell$ = TrimAll$(cell$)
    If Len(cell$) < 2 Or Len(cell$) > 3 Then CellOK% = 0: Exit Function

    ch$ = Mid$(cell$, 1, 1)
    c% = LetterToCol%(ch$)
    If c% < 1 Or c% > CMAX% Then CellOK% = 0: Exit Function

    num$ = Mid$(cell$, 2)
    If num$ = "" Then CellOK% = 0: Exit Function

    For i% = 1 To Len(num$)
        d$ = Mid$(num$, i%, 1)
        If IsDigit%(d$) = 0 Then CellOK% = 0: Exit Function
    Next i%

    rr% = 0
    For i% = 1 To Len(num$)
        rr% = rr% * 10 + (Asc(Mid$(num$, i%, 1)) - Asc("0"))
    Next i%

    If rr% < 1 Or rr% > RMAX% Then CellOK% = 0: Exit Function

    r% = rr%
    CellOK% = -1
End Function


Reply


Messages In This Thread
RE: QB64PE Excel-type spreadsheet supporting formulas and QB64PE macros? - by Petr - 01-26-2026, 09:23 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  QB64pe and Home Automation dano 3 217 02-12-2026, 02:27 PM
Last Post: mdijkens
Question qb64pe's translation of .bas to .cpp ? Fifi 6 481 01-21-2026, 08:51 PM
Last Post: Fifi
Question Finaly, qb64pe-4.3.0 could work on macOS 10.13.6 (High Sierra) ! Fifi 0 147 01-20-2026, 02:53 PM
Last Post: Fifi
  a question about OpenGL in QB64pe: TempodiBasic 11 1,812 11-22-2025, 05:47 PM
Last Post: TempodiBasic
Question Latest version of QB64PE or QB64 compatible with Windows XP (32-bit)? madscijr 14 1,997 09-30-2025, 08:10 AM
Last Post: hsiangch_ong

Forum Jump:


Users browsing this thread: 1 Guest(s)