Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475

    [Delphi] Foglio di calcolo

    Salve a tutti!

    Sono inesperto e masochista, combinazione che può facilmente portare a realizzare un foglio di calcolo come Excel in delphi. Folle vero?

    Comunque. Sto usando un frame che fa da foglio di calcolo, in questo modo posso aggiungere altri fogli come fa excel ridisegnando il frame. Su questo frame uso una NiceGrid per simulare excel. La NiceGrid è un componente che ho trovato su internet, funziona esattamente come le StringGrid ma è molto più bello.
    Il problema è che l'utente scrive le formule, e io voglio fargli vedere il risultato. Perciò ho pensato di aggiungere un'altra nicegrid invisibile. Su quella invisibile tengo le formule, su quella visibile scrivo il risultato.

    Il problema è che l'utente scrive su quella visibile. Il problema è che non so come sincronizzare le celle.

    Quando l'utente scrive (evento OnChange) basta che dico che il contenuto della stessa cella della griglia invisibile diventi uguale a quella in cui scrive. Poi quando l'utente esce dalla cella (OnColRowChanged) io faccio il calcolo della formula e scrivo il risultato nella cella... e scatta di nuovo onChange che azzera la formula nella griglia nascosta.

    La mia idea è stata di spostare il ragionamento nel onKeyDown. una cosa del tipo:

    procedure TSheet.VisualGridKeyDown(Sender: TObject; var Key: Word;
    Shift: TShiftState);
    begin
    HideGrid.OnKeyDown(Sender, key, shift);
    end;

    Così poi nell'evento onColRowChanged facevo il calcolo. Però quando premo un tasto sulla visualgrid mi da un access violation at address 0000000000. E non capisco perchè!!!

  2. #2
    premetto che esistono componenti già fatti disponibili per delphi che sono simili ad excel.
    Se invece il tuo è un esercizio va bene, è una buona palestra.
    Io però non creerei una nuova grid nascosta ma una struttura dati idonea a memorizzare le formule inserite dall'utente.
    Prima di tutto verifica che il componente che utilizzi non preveda già un sistema di memorizzazione di dati utente per ogni cella, altrimenti puoi iniziare da una banale matrice di stringhe che corrisponda alle coordinate del tuo foglio di alcolo, ma che poi devi perfezionare per limitare l'occupazione di memoria, mi viene in mente una tabella hash che ha come chiave un riferimento alla cella (anche una stringa costituita delle due coordinate affiancate va bene).
    All'eventule onclick o onkeydown leggi la formula associata, la risolvi e la visualizzi nella cella relativa.
    spero di esserti stato utile
    ciao
    sergio

  3. #3
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475
    Il problema non è tanto la memorizzazione delle formule, ma evitare il cambiamento a cascata in OnChange. Il momento critico per me è la memorizzazione della formula.

    Se lo faccio in OnChange, riesco a memorizzarla ma ho il cambiamento a cascata nel dare il risultato.
    Se lo faccio in OnKeyDown, riesco a evitare il cambiamento a cascata quando do il risultato ma non riesco a sincronizzare le due celle.

    Adesso mi è venuto il sospetto che con onKeyPress posso risolvere tutto... provo e ti faccio sapere.

    Però mi interessa molto quella storia della tabella hash. Potresti spiegarmi cosa intendi? Non sono pratico di queste cose...

    Grazie ciao

  4. #4
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475
    Ok, questo l'ho risolto. Bastava metterlo in OnKeyUp, tutto qui ^^

    Ora però ho un problema meno banale, sostituire alle coordinate il contenuto della cella. Ovvero. Mettiamo che la cella A15 contiene 2, mentre la cella B15 contiene 3. L'utente scrive nella cella C15 '=A15^B15', e io devo trasformare quella stringa in '2^3'. Per il calcolo non c'è problema, ho un parser che fa tutto da solo... ma devo riuscire a passargli la stringa corretta. Non so come riconoscere all'interno di una stringa le coordinate *_*

    Idee?

  5. #5
    puoi leggere i singoli caratteri di una stringa in Pascal in stile C

    codice:
    var
      s, str : string;
      i : integer;
    begin
      str := 'pippo';
      for i := 1 to Length(str) do
        s := str[i];
    end;
    e discriminare le due parti della coordinata.
    ciao
    sergio

  6. #6
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475
    Problema in via di risoluzione, finalmente... ^^

    Grazie dell'aiuto, l'idea di cercare le coordinate così era buona, infatti sembra funzionare. Da qui dovrei riuscire da solo. Intanto pubblico il codice, nel caso (improbabile ^^) che a qualcuno interessasse :P

    function TSheet.solve(c, r: integer): string;
    var exp,sc:string;
    i,p1,p2:integer;
    begin
    exp:=(HideGrid[c,r]);
    if cells[c,r].formula then
    begin
    if cells[c,r].formula then delete(exp,1,1);
    while letter(exp) do
    for i:= 1 to (length(exp)-1) do
    if isletter(exp[i]) then
    begin
    sc:='';
    sc:=exp[i];
    if isnumber(exp[i+1]) then
    begin
    sc:= sc + exp[i+1];
    if ((i+2)<=length(exp)) then
    if isnumber(exp[i+2]) then sc:= sc + exp[i+2];
    if ((i+3)<=length(exp)) then
    if isnumber(exp[i+3]) then sc:= sc + exp[i+3];
    exp:=replace(exp, sc, solve(tradcol(sc), tradrow(sc), c, r));
    end
    else
    if UpCase(exp[i]) = UpCase(parameter) then
    begin
    exp:=replace(exp, parameter, solve(Visualgrid.Col,visualgrid.Row,c,r));
    end;
    end;
    exparser1.Expression.Clear;
    exparser1.Expression.add(exp);
    result:=exparser1.F([]);
    end
    else
    begin
    if cells[c,r].empty then result:='0';
    if cells[c,r].data then result:=visualgrid.Cells[c,r];
    end;
    end;
    Parameter è un char che si può usare per calcolare velocemente formule. Del tipo, in una cella c'è scritto '=k^2', e ogni volta che ci si sposta di cella in cella, il valore viene ricalcolato con il contenuto della cella.
    Cells[c,r] è un array di record che contiene tre boolean, per controllare se contiene formule, dati, o niente.
    Letter(s) è una funzione che da vero se la stringa contiene almeno una lettera. IsLetter fa la stessa cosa su un char. IsNumber direi che si spiega da solo.
    Replace sostituisce all'interno di una stringa una sottostringa con una nuova.
    TradCol e TradRow trasformano la stringa delle coordinate in coordinate numeriche per risolvere la nuova cella.
    Replace è l'unica mediamente interessante, quindi posto anche quella.

    function TSheet.replace(s, old, new: string): string;
    var p1,p2:integer;
    sx,s1,s2:string;
    begin
    sx:=s;
    if pos(old, sx) > 0 then
    begin
    p1:=pos(old, sx);
    p2:=p1 + length(old);
    s1:=copy(sx, 1, p1-1);
    s2:=copy(sx, p2, length(sx)-(p2-1));
    result:= s1 + new + s2;
    end
    else
    result:=sx;
    end;
    Chissà che non servano a qualcuno (ne dubito xD) ^^

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.