Avatar billede skindbeni Nybegynder
20. april 2008 - 19:21 Der er 15 kommentarer og
2 løsninger

Hvordan vil I gribe dette an? Gemme data i skatteberegning

Hej.

Jeg har et stort ønske om at bygge mit eget skatteberegningsprogram, da dette emne interesserer mig qua min revisorbaggrund. Det er kun hobbyprogrammering, men kunne være rart at bygge et brugbart og funktionelt program.

Mange dele af programopbygningen er lavet. Jeg har sågar lavet det om nogle gange. Selve beregningen foretages rimelig fint osv., men mit store problem er at få programmet lavet, således at man kan gemme data på en ordentlig måde.

Jeg ser det som to dele. Den ene del handler om, at det skal være muligt at gemme og åbne forskellige "skatteberegninger/personer/kunder" (kald det hvad man vil), således at man kan åbne en beregning frem, ændre i den, lukke den igen for at arbejde i den en anden dag samt derimellem evt. arbejde på andre personer/skatteberegninger.

Det er et rimelig kompleks system med mange data, der skal lagres for hver beregning, heraf langt det meste som integer værdier (fx løn, SU, pension, renteindtægter, befordring osv.). Jeg vil gætte på, at der ligger 125-150 felter for enlige og 250-300 felter, når personerne er gift og begge ægtefællers data skal bruges. Langt de fleste værdier er 0 medmindre der er et relevant beløb at indtaste.

Jeg har forsøgt mig med INI-filer som lagring og derefter hente dataene ind i nogle clientDataSet's og herfra bearbejde dataene. Dette er en blandet fornøjelse.

Databaser har også været en overvejelse, men jeg havde håbet, at det kunne gøres mere simpelt - især for slutbrugeren, således man ikke skulle installere database. Jeg har kun Firebird i tankerne, hvis det bliver aktuelt.

Jeg ser frem til at høre forslag, lærerige kommentarer og input af alle karakterer.
Avatar billede kroning Nybegynder
20. april 2008 - 20:53 #1
Kan du ikke bruge TClientDataSet´s SaveToFile funktion som har mulighed for at gemme som  binary, XML, eller UTF8.
Avatar billede kroning Nybegynder
20. april 2008 - 20:54 #2
Hvis det ikke drejer sig om rigtig mange personer/ægtefæller burde det være en let og brugbar løsning.
Avatar billede skindbeni Nybegynder
20. april 2008 - 21:59 #3
Hej Kroning.

Tjo, det forsøgte jeg også i min tidligere "udgave." Lige nu roder jeg bare rundt med ca. 10 clientdatasets pr. "person". Måske ikke den bedste løsning, men det gav et fint overblik i selve beregningen, når jeg kunne opdele mine data i grupper i clientdataset'ene.

Men måske er det den bedste løsning alligevel? Jeg tygger lidt på det. og afventer, om der kommer andre bud.
Avatar billede martinlind Nybegynder
20. april 2008 - 22:50 #4
det er klart nemmest med kroning måde, den kan også nemt udvides til at køre på et netværk :-)

hvis det er det med at du fåer en fil for hvert ds, så kan du lave noget "trylleri" og lægge det i EN fil, med brug af TStream.
Avatar billede arne_v Ekspert
21. april 2008 - 02:34 #5
Hvis du bruger en embedded database skal den ikke installeres.
Avatar billede Slettet bruger
21. april 2008 - 09:10 #6
du kan også bruge XLM, dette format er lidt mere informativ og logisk opbygget end en .ini fil. Her er en artikel: http://www.udvikleren.dk/XML/Article.aspx/226/
Avatar billede hrc Mester
21. april 2008 - 09:22 #7
Nu plejer jeg at splitte delene op i isolerede objekter, såsom person, adresse, konto og den slags. De nedarver alle fra samme baseklasse der fordrer at man implementerer en ReadFromStream og SaveToStream.

Til at læse og skrive bruger jeg TReader og TWriter-klasserne:

procedure MyObject.SaveToStream(aStream: TStream);
var
  Writer: TWriter;
begin
  Writer := TWriter.Create(aStream,1024);
  try
    Writer.WriteInteger(fData1);
    Writer.WriteInteger(fData2);
    Writer.WriteBoolean(fData3);
    Writer.FlushBuffers;
  finally
    Writer.Free;
  end;
end;

I min LoadFromStream henter jeg data i nøjagtig samme måde:

procedure MyObject.LoadFromStream(aStream: TStream);
var
  Reader: TReader;
begin
  Reader := TReader.Create(aStream,1024);
  try
    fData1 := Reader.ReadInteger;
    fData2 := Reader.ReadInteger;
    fData3 := Reader.ReadBoolean;
    Reader.FlushBuffers;
  finally
    Reader.Free;
  end;
end;

(FlushBuffer er vigtig; virker ikke uden).

Nogle gange sætter jeg et versionsnummer foran dataklumpen, så jeg kan læse forskellige versioner af samme:

const
  CurrentVersion = 3;

procedure MyObject.SaveToStream(aStream: TStream);
var
  Writer: TWriter;
begin
  Writer := TWriter.Create(aStream,1024);
  try
    Writer.WriteInteger(CurrentVersion);
    Writer.WriteInteger(fData1);
    Writer.WriteInteger(fData2);
    Writer.WriteBoolean(fData3);
    Writer.FlushBuffers;
  finally
    Writer.Free;
  end;
end;

I min LoadFromStream henter jeg data i nøjagtig samme måde:

procedure MyObject.LoadFromStream(aStream: TStream);

  procedure ReadData1(aReader: TReader);
  begin
    fData1 := Reader.ReadInteger;
  end;

  procedure ReadData2(aReader: TReader);
  begin
    fData1 := Reader.ReadInteger;
    fData3 := Reader.ReadBoolean;
  end;

  procedure ReadData3(aReader: TReader);
  begin
    fData1 := Reader.ReadInteger;
    fData2 := Reader.ReadInteger;
    fData3 := Reader.ReadBoolean;
  end;

var
  Reader: TReader;
begin
  Reader := TReader.Create(aStream,1024);
  try
    case Reader.ReadInteger of // Hent versionsnummer
      1: ReadData1(aReader);
      2: ReadData2(aReader);
      3: ReadData3(aReader);
    end;
    Reader.FlushBuffers;
  finally
    Reader.Free;
  end;
end;
Avatar billede hrc Mester
21. april 2008 - 09:31 #8
Retter lige en hurtig copy-paste fejl:

  procedure ReadData1(aReader: TReader);
  begin
    fData1 := aReader.ReadInteger;
  end;

  procedure ReadData2(aReader: TReader);
  begin
    fData1 := aReader.ReadInteger;
    fData3 := aReader.ReadBoolean;
  end;

  procedure ReadData3(aReader: TReader);
  begin
    fData1 := aReader.ReadInteger;
    fData2 := aReader.ReadInteger;
    fData3 := aReader.ReadBoolean;
  end;

Jeg bruger ovenstående teknik til at gemme heterogene data i samme fil. Eksempelvis gemmer jeg data i mit "password-library" på den måde. Da alle sider i det program er konfigurérbare er det forskellige data der gemmes.

I øvrigt. XML er ikke dumt at gemme det i, men det er besværligt at administrere, endsige navigere rundt i og jeg bruger det kun når data skal kunne exporteres til andre programmer. Det kan godt være relevant i dit tilfælde.
Avatar billede martinlind Nybegynder
21. april 2008 - 11:12 #9
hrc mfl. >> det er en fed "delphi-like" måde at bruge delphi obj.-stream faciliteter, men hvis du vil optimere det lidt og ungå en masse manuel kode hvergang du retter lidt osv. så flyt din base-class til TPersistent, det har den kæmpe fordel at du kan lave dine data-felter som published properties og derved benytte de indbyggede stream-funktioner, så slipper du for selv at skrive dine reader/writer function.

Det er sådan delphi gemmer sine forms, det funker fint at bruge det, lavede på et tidspunkt et program der tilrettede sin fuldstændig, både GUI og filer tilpassede sig selv, når jeg lige fandt på et felt mere, så tilføjede jeg det bare til mit dataobject som en published prop. og intet andet, så kørte det ! ret nice ;-) bare ved brug af TPersistent classen
Avatar billede Slettet bruger
21. april 2008 - 11:23 #10
enig, man kan også lave nogle fede plugins bare ved at streame sine objecter
Avatar billede hrc Mester
21. april 2008 - 11:42 #11
martin: Tak for tippet.

Jeg glemte at skrive i ovenstående, at TReader og TWriter primært blev brugt til at gemme objekternes properties, så noget vidste jeg da. At størstedelen af arbejdet er lavet i TPersistent, havde jeg ikke fanget. Skal undersøge om jeg er gået over åen efter vand, men kan nu ellers godt lide at have 100% kontrol over hvad/hvordan tingene gemmes.

(det må være noget med at TPersistent bruger RTTI (RunTime Type Information) til automatisk gemme de private værdier, ikke?)

Tror dog ikke den kan håndtere varianten med versionsnummeret.
Avatar billede skindbeni Nybegynder
23. april 2008 - 22:27 #12
Hej alle.

Vil lige orientere om, at jeg ikke har i sinde at brænde jer af mht. point. Delphi er en af mine hobbyer og jeg arbejder ikke på det hver dag.

Jeg kigger på det i weekenden og vender tilbage.
Avatar billede skindbeni Nybegynder
29. april 2008 - 17:49 #13
Jeg prøver at arbejde hen mod at bruge Firebird som embedded database og hente data over i et clientdataset.

Vil i smide svar, så vil jeg fordele points efter, hvad jeg har nydt mest af :o)
Avatar billede hrc Mester
29. april 2008 - 21:46 #14
Held og lykke med det. Du kan eventuelt kombinere databasen med at streame data ned i blob-felter. Blob er både godt og skidt, men nogle gange er det praktisk at kunne gemme grupperede data i én klump.
Avatar billede martinlind Nybegynder
30. april 2008 - 13:46 #15
hrc >> du kan læse mere i delphi-hjælpen, TPersisten kan håndtere det din form kan håndtere, og det er en del, det man så kan er at lave uderdef. prop. og der override Reader/writer funktioner til de spec. props.

Skindbeni >> Godt valg :-), jeg har brugt Firebird i 3-4 år nu og den er super, gui til den kan være IBExpert personal-edittion, den er gratis og kan det du har behov for.
Avatar billede hrc Mester
30. april 2008 - 23:26 #16
martin: Jeg skal nok pløje hjælpen igennem, når jeg har brug for at streame igen. Desværre synes jeg ikke den store forkromede online-hjælp i D2007 er noget værd - endnu. Jeg smutter hellere ud i VCL-sourcen.
Avatar billede martinlind Nybegynder
01. maj 2008 - 17:21 #17
Jeg pløjede også mest rundt i D1+D3 online-hjælpen, nu er det min "korttids-hukommelse" og sourcen jeg kører på :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester