fpspreadsheet und Rahmen

Rund um die LCL und andere Komponenten
JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

fpspreadsheet und Rahmen

Beitrag von JosefKoller »

Hallo,

ich probier schon dauernd rum und bekomm einfach keinen Rahmen um meine Zelle(n).

ich hab einfach ein sWorksheetGrid aufs Formular gezogen.

Dann bei einem ButtonClick folgendes dazugeschrieben:

Code: Alles auswählen

 
procedure TForm1.Button1Click(Sender: TObject);
var
  bs: TsCellBorder;
  bsl:TsCellBorderStyle;
  clr:TsColor;
begin
  bsl.Color:=scRed;
  bsl.LineStyle:=lsThick;
  sWorksheetGrid1.Worksheet.WriteUTF8Text(1,1,'Test');
  sWorksheetGrid1.Worksheet.WriteBackgroundColor(1,1,clSilver);
  //sWorksheetGrid1.Worksheet.WriteBorderStyle(1,1,[cbNorth, cbWest, cbEast, cbSouth],lsThick,scRed);
  sWorksheetGrid1.Worksheet.WriteBorderStyle(1,1,bs.cbSouth,lsThick,scRed);
end; 
 
Kann mir jemand sagen, wie ich einfach einen Rahmen (oben,rechts,unten,links) um eine oder mehrere Zellen zustande bringe.

Bei dem obigem Beispiel funktioniert nur die Hintergrundfarbe und die Textausgabe.

Danke.

Josef

wp_xyz
Beiträge: 5130
Registriert: Fr 8. Apr 2011, 09:01

Re: fpspreadsheet und Rahmen

Beitrag von wp_xyz »

Die WriteBorderStyle-Kommandos, die du verwendest, sind dafür da, die Darstellung des Rahmens zu definieren, wenn er aktiv wäre. Du musst mit WriteBorders noch festlegen, wo Rahmenlinien eingeblendet werden sollen:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
begin
  sWorksheetGrid1.Worksheet.WriteUTF8Text(1,1,'Test');
  sWorksheetGrid1.Worksheet.WriteBackgroundColor(1,1,clSilver);
  sWorksheetGrid1.Worksheet.WriteBorderStyle(1,1, cbSouth, lsThick,scRed);  // der untere Rahmen von Zelle 1,1 (=B2), falls aktiv, soll eine dicke rote Linie sein
  sWorksheetGrid1.Worksheet.WriteBorders(1, 1, [cbSouth]);  // schaltet die untere Rahmenlinie von Zelle 1,1 (=B2) ein
end; 
Schau dir die Dokumentation an, die sich im chm-Format für deine aktuelle Installtion im Ornder docs befindet (oder http://wiki.lazarus.freepascal.org/FPSp ... ll_borders für die aktuelle trunk-Version).

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: fpspreadsheet und Rahmen

Beitrag von JosefKoller »

Hallo,

Danke für die Antwort.

so, wie du das schreibst und wie es auch in den Demos oder auf der von Dir genannten Seite steht, hab ich es auch versucht.

Letztlich war oder ist es ganz einfach:

Ich hab meine Testkomponente wahrscheinlich durch das viele Rumprobieren ruiniert. Ich hab dann alles gelöscht und nochmal neu angefangen.

So funktioniert es nun:

Code: Alles auswählen

 
...
for i:=0 to 11 do
  begin
    sWorksheetGrid1.Worksheet.WriteFont(iLast+1,i,'Calibri',9, [],clBlack);
    sWorksheetGrid1.Worksheet.WriteBackgroundColor(iLast+1,i,clSilver);
    sWorksheetGrid1.Worksheet.WriteBorders(iLast+1,i,[cbNorth, cbEast, cbWest, cbSouth]);
    sWorksheetGrid1.Worksheet.WriteBorders(iLast+2,i,[cbSouth, cbEast, cbWest]);
  end;
  sWorksheetGrid1.RowCount:=iLast+3;
...
 


Man muß nur aufpassen, daß die Background Zuweisung vor den Borderzuweisungen steht. Wenn Background nach Border kommt übermalt der Background die Borders, zumindest nach meinem jetzigen "Versuchsstand".

Die Stärke der Borderlinien, die Farbe, usw. muß ich noch probieren.

Ein Problem hab ich noch:
Bei der Zuweisung von Borders wird immer die Zelle verwendet. Kann man auch über einen Bereich einen Rahmen legen, also z.B. von Zelle 0,0 bis Zelle 10,10?

Danke.

Josef



Ciao

Josef

wp_xyz
Beiträge: 5130
Registriert: Fr 8. Apr 2011, 09:01

Re: fpspreadsheet und Rahmen

Beitrag von wp_xyz »

JosefKoller hat geschrieben:Man muß nur aufpassen, daß die Background Zuweisung vor den Borderzuweisungen steht. Wenn Background nach Border kommt übermalt der Background die Borders, zumindest nach meinem jetzigen "Versuchsstand".
Das kann ich nicht bestätigen. Aber wie das folgende Code-Fragment zeigt, wird der Borderstyle nur dann berücksichtigt, wenn die Borders schon aktiv sind. Unschön... Ich denke, ich werde das bei Gelegenheit ändern.

Code: Alles auswählen

 
uses
  fpspreadsheet, fpstypes, fpsopendocument;
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
var
  book: TsWorkbook;
  sheet: TsWorksheet;
begin
  book := TsWorkbook.Create;
  sheet := book.AddWorksheet('test');
 
  // 1. BackgroundColor - 2. Borders - 3. BorderStyle
  sheet.WriteBackgroundColor(0,0, scYellow);
  sheet.WriteBorders(0,0, [cbSouth]);
  sheet.WriteBorderStyle(0, 0, cbSouth, lsThick, scBlue);
  sheet.WriteNumber(0,0, 1.0);
 
  // 1. BackgroundColor - 2. BorderStyle - 3. Borders
  sheet.WriteBackgroundColor(0,1, scYellow);
  sheet.WriteBorderStyle(0,1, cbSouth, lsThick, scBlue);
  sheet.WriteBorders(0,1, [cbSouth]);
  sheet.WriteNumber(0,1, 1.0);
 
  // 1. Borders - 2. BorderStyle - 3. BackgroundColor
  sheet.WriteBorders(0,2, [cbSouth]);
  sheet.WriteBorderStyle(0,2, cbSouth, lsThick, scBlue);
  sheet.WriteBackgroundColor(0,2, scYellow);
  sheet.WriteNumber(0,2, 2.0);
 
  // 1. BorderStyle - 2. Borders - 3. BackgroundColor
  sheet.WriteBorderStyle(0,3, cbSouth, lsThick, scBlue);
  sheet.WriteBorders(0,3, [cbSouth]);
  sheet.WriteBackgroundColor(0,3, scYellow);
  sheet.WriteNumber(0,3, 2.0);
 
  book.WriteToFile('test.ods', sfOpenDocument, true);
  book.Free;
end; 
JosefKoller hat geschrieben:Bei der Zuweisung von Borders wird immer die Zelle verwendet. Kann man auch über einen Bereich einen Rahmen legen, also z.B. von Zelle 0,0 bis Zelle 10,10?
Nicht automatisch, leider etwas benutzerunfreundlich: Du musst die Zellen einzeln durchlaufen und die Border entsprechend der Position der Zellen richtig setzen, Für den Fall einer Spalte (0,0) - (10,0) wäre das etwa so (ein Rechteck wie in deinem Beispiel wäre entsprechend, nur mehr Schreibarbeit: Eckpunkte, innere Randzeile oben/unten, innere Randspalte links/rechts):

Code: Alles auswählen

 
var
  r: Integer;
...
  sheet.WriteBorders(0, 0, [cbNorth, cbWest, cbEast]);  // oberste Zelle
  sheet.WriteBorders(10, 0, [cbSouth, cbWest, cbEast]);  // unterste Zelle
  for r := 1 to 9 do   // innere Zellen 
    sheet.WriteBorders(r, 0, [cbWest, cbEast]);
 
Du musst dabei beachten, dass eine Linie zwischen aneinander angrenzenden Zellen immer dann gezeichnet wird, wenn mindestens eine von ihnen die Border gesetzt hat.

wp_xyz
Beiträge: 5130
Registriert: Fr 8. Apr 2011, 09:01

Re: fpspreadsheet und Rahmen

Beitrag von wp_xyz »

wp_xyz hat geschrieben:
JosefKoller hat geschrieben:Aber wie das folgende Code-Fragment zeigt, wird der Borderstyle nur dann berücksichtigt, wenn die Borders schon aktiv sind. Unschön... Ich denke, ich werde das bei Gelegenheit ändern.
Was nun geschehen ist... (siehe r4411).

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: fpspreadsheet und Rahmen

Beitrag von JosefKoller »

Hallo,

Danke für die Hinweise.
Es kann natürlich sein, daß ich bei meiner Rumprobierei die von dir genannte Reihenfolge bei den Rahmen nicht einhielt.
Ist immer schwierig beim Rumprobieren dann auf den tatsächlichen "Fehler" zu stoßen.

Da ich für einen "Bereichsrahmen" keine passenden Funktionen oder Prozeduren fand, dachte ich mit schon, daß ich das ganze mit einer Schleife realisieren muß.

Ansonsten, Klasse, diese Komponente.

Bisher versuchte ich immer mit einem Memo-Feld folgendes zu realisieren:

Anfangs kommt ein Schwung an Textzeilen.

Nach diesen Textzeilen käme dann eine Tabelle. Und gerade da hapert es bei anderen Komponenten. Mit Memo bekomm ich allenfalls mit /t, also mit Tabulatoren eine gewisse Struktur hin.
Wird aber auch fast unmöglich, wenn einzelne Spalten in der Breite größer sind, als die Tab-Einstellung usw. Mit RichEdit muß man sich schon sehr gut im RTF-Format auskennen, um eine Tabelle hinzubekommen.

Da ist fpSpreadSheet genau das Richtige für mich. Man kann das Ding dann als xls-Datei abspeichern und diese Datei dann weitergeben. Mit xls-Format kann jedes Betriebssystem was anfangen.

Wie gesagt, einfach gut, das Ding.

Nun aber doch noch 2 Fragen:

1.Kann man die Komponenten auch auf Mac für Lazarus installieren? Ein Freund von mir hat Mac und macht bei der Entwicklung dieses Auswerteprogramms mit. Wär blöd, wenn er fpSpreadsheet nicht installieren könnte.

2. Der "Komponenteninhalt" muß bei mir in einer Datenbank gespeichert werden. Es gibt ...savetostream und loadfromstream.
Gibt es da was zu beachten, wenn ich den Inhalt mittels streams in einem Datenbankfeld vom Typ blob speichere und lade?

Ich frag lieber, bevor ich wieder lang rumprobiere?

Danke.

Josef

Ach und noch was:
Bei Allen Beispielen, die ich sah wurde der von dir gezeigte Aufbau verwendet:

Code: Alles auswählen

 
...
var
  book: TsWorkbook;
  sheet: TsWorksheet;
begin
  book := TsWorkbook.Create;
  sheet := book.AddWorksheet('test');
...
 
Ich hab einfach nur die ein tsWorksheetGrid aufs Formular gezogen und damit gearbeitet. Ist das falsch??

wp_xyz
Beiträge: 5130
Registriert: Fr 8. Apr 2011, 09:01

Re: fpspreadsheet und Rahmen

Beitrag von wp_xyz »

JosefKoller hat geschrieben:1.Kann man die Komponenten auch auf Mac für Lazarus installieren? Ein Freund von mir hat Mac und macht bei der Entwicklung dieses Auswerteprogramms mit. Wär blöd, wenn er fpSpreadsheet nicht installieren könnte.
Ich selbst habe keinen Zugang zu einem Mac und fpspreadsheet daher so noch nicht getestet. Aber es hätte sich sicher schon jemand gemeldet, wenn es nicht ginge. Zumindest das nicht-visuelle Package ist sehr allgemein gehalten und müsste immer funktionieren. Die visuellen Komponenten (das Grid etc) könnten evtl Probleme machen.
JosefKoller hat geschrieben:2. Der "Komponenteninhalt" muß bei mir in einer Datenbank gespeichert werden. Es gibt ...savetostream und loadfromstream.
Gibt es da was zu beachten, wenn ich den Inhalt mittels streams in einem Datenbankfeld vom Typ blob speichere und lade?
Du musst halt peinlich genau darauf achten, dass in derselben Reihenfolge, in der geschrieben wird, auch wieder gelesen wird. Ansonsten verstehe ich nicht genau, was du da machen willst. Um den Inhalt der Spreadsheet-Zellen (falls du das meinst) in einer Datenbank zu speichern, gibt es einige Beispiele im Installationsordner, im wiki, sowie die speziellen Export-Komponenten im Package laz_fpspreadsheetexport_visual.
JosefKoller hat geschrieben:Bei Allen Beispielen, die ich sah wurde der von dir gezeigte Aufbau verwendet...Ich hab einfach nur die ein tsWorksheetGrid aufs Formular gezogen und damit gearbeitet. Ist das falsch??
Kommt drauf an... Wenn du nur eine xls-Datei erzeugen willst, ohne sie anzuzeigen, ist meine Version günstiger, weil der Overhead mit den visuellen Komponenten wegfällt, und das geht auch in einem Konsolen-Programm. Um ein Spreadsheet anzuzeigen, führt dagegen kein Weg am WorksheetGrid vorbei.

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: fpspreadsheet und Rahmen

Beitrag von JosefKoller »

Hallo,
JosefKoller hat geschrieben:2. Der "Komponenteninhalt" muß bei mir in einer Datenbank gespeichert werden. Es gibt ...savetostream und loadfromstream.
Gibt es da was zu beachten, wenn ich den Inhalt mittels streams in einem Datenbankfeld vom Typ blob speichere und lade?

Du musst halt peinlich genau darauf achten, dass in derselben Reihenfolge, in der geschrieben wird, auch wieder gelesen wird. Ansonsten verstehe ich nicht genau, was du da machen willst. Um den Inhalt der Spreadsheet-Zellen (falls du das meinst) in einer Datenbank zu speichern, gibt es einige Beispiele im Installationsordner, im wiki, sowie die speziellen Export-Komponenten im Package laz_fpspreadsheetexport_visual.
So, wie mir das vorstellte funktioniert es natürlich nicht.

Was ich will:
Ich will das worksheetgrid samt "Struktur und Inhalt" in einen Stream speichern, diesen Stream in ein Datenbank Tabellenfeld schreiben und eben wieder zurück von diesem Tabellenfeld in ein worksheetgrid.

Mit

Code: Alles auswählen

 
var
  ST:TMemoryStream;
begin
  ST:=TMemoryStream.Create;
  sWorksheetGrid1.SaveToStream(ST);
  //sWorksheetGrid1.SaveToFile('test.xls');
  ST.Position:=0;
  dmbees.ZQPedigree.Edit;
  dmbees.ZQPedigreeped_blob.LoadFromStream(ST);
  dmbees.ZQPedigree.Post;
  dmbees.ZQPedigree.Refresh;
  st.Free;                        
 
funktioniert es mal nicht. In das Tabellen-Blob-Feld wird lediglich ein "XML-Grid Rumpf" geschrieben.

Code: Alles auswählen

 
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
  <grid version="3">
    <saveoptions create="False" position="False"/>
  </grid>
</CONFIG>
 
Dann dachte ich, ich nehm die Komponente

SimpleXMLExporter1.

Code: Alles auswählen

 
var
  ST:TMemoryStream;
begin
 
  ST:=TMemoryStream.Create;
  SimpleXMLExporter1.FileName:='simple.xml';
  SimpleXMLExporter1.ExportToStream(ST);
  SimpleXMLExporter1.Execute;
 
Wenn ich damit starte, soll aber ein Dateiname angegeben werden und wenn ich das mache, dann soll auch noch ein Dataset angegeben werden.

Dabei will ich weder in eine Datei noch in irgendein Dataset schreiben.

Ich will lediglich den Gridinhalt in einem Tabellenfeld ablegen und von diesem Tabellenfeld aus, wieder ein Grid mit dem gespeicherten Inhalt füllen.

Also zusammengefaßt:

Wie bekomme ich den Gridinhalt in einen Stream und von dem Stream wieder zurück in ein Grid?

Danke.

Josef

wp_xyz
Beiträge: 5130
Registriert: Fr 8. Apr 2011, 09:01

Re: fpspreadsheet und Rahmen

Beitrag von wp_xyz »

Das Grid hat alle Daten sowie alle Einstellungen in dem Worksheet, das es anzeigt. Daher musst du nicht WorksheetGrid.SaveToStream aufrufen, sondern WorksheetGrid.Workbook.WriteToStream. Und natürlich zum Lesen dann WorksheetGrid.Workbook.ReadFromStream. Letzendlich speicherst du dann den Inhalt einer Excel-Datei in dem Blob-Feld.

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: fpspreadsheet und Rahmen

Beitrag von JosefKoller »

Hallo,

besten Dank.

Hab das nun so ausprobiert, wie du geschrieben hast. Das speichern in ein Datenbank Tabellen blob-Feld funktioniert.

Code: Alles auswählen

 
procedure Tfpedigreeueber.Button2Click(Sender: TObject);
var
  ST:TMemoryStream;
begin
  ST:= TMemoryStream.Create;
  sWorksheetGrid1.Workbook.WriteToStream(ST,sfExcel2);
  ST.Position:=0;
  dmbees.ZQPedigree.Edit;
  dmbees.ZQPedigreeped_blob.Clear;
  dmbees.ZQPedigreeped_blob.LoadFromStream(ST);
  dmbees.ZQPedigree.Post;
  dmbees.ZQPedigree.Refresh;
  ST.Free;
end;        
 
Das von dir vorgeschlagene "WorksheetGrid.Workbook.ReadFromStream" funktioniert dagegen nicht. Im Grid wird nach dem Laden nichts angezeigt.

Code: Alles auswählen

 
procedure Tfpedigreeueber.Button4Click(Sender: TObject);
var st:TMemoryStream;
begin
  st:=TMemoryStream.Create;
  st.Position:=0;
  dmbees.ZQPedigreeped_blob.SaveToStream(st);
  st.Position:=0;
  sWorksheetGrid1.Workbook.ReadFromStream(st,sfExcel2);
 
  //st.Position:=0;
  //st.SaveToFile('tmp/test2.xls');
  //sWorksheetGrid1.LoadFromSpreadsheetFile('tmp/test2.xls');
  //DeleteFileUTF8('tmp/test2.xls');
  st.Free;
end;     
 
Wenn ich das direkte Lesen vom Stream in das grid auskommentiere und den oben auskommentierten Code starte (also den stream in einer Datei speichern und diese Datei dann ins grid laden, dann funktioniert es.

Der Umweg über eine Datei ist irgendwie blöd. Hast du sonst noch eine Idee, wie ich den stream direkt ins Grid bekomme?

Danke.

Josef

wp_xyz
Beiträge: 5130
Registriert: Fr 8. Apr 2011, 09:01

Re: fpspreadsheet und Rahmen

Beitrag von wp_xyz »

Oje, da hab ich mal wieder zuviel versprochen... In den Sourcen hätte ich sehen können, dass das Grid noch Vorbereitungen machen muss, bevor der Stream in das Workbook eingelesen werden kann. Ich denke, ich werden das Grid mit einer Methode ReadFromStream (analog zu ReadfromFile) ausstatten, in der alles erledigt wird. Bitte gib mir etwas Zeit.

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: fpspreadsheet und Rahmen

Beitrag von JosefKoller »

Hallo,

und ich dacht schon, ich wär wieder zu blöd dazu.

Nur kein Streß. Ich mach einfach mal weiter und lese den stream über eine Datei ein bis du soweit bist.

Bekomm ich irgendwie mit, wann Du fertig bist?

Und nochwas:
ich hab das da gefunden:

sWorksheetGrid1.FocusRectVisible:=False;

und dachte... hmmh... das ist prima. Ich kann dann von dem Grid 2 Versionen verwirklichen. Einmal nur Ansicht (also editing auf false) und eben den Focus weg
und im Bearbeiten-Modus, editing auf true und eben den Focus ein.

Nur bei

sWorksheetGrid1.FocusRectVisible:=False;

tut sich nix. Egal was ich schreibe, also true oder false, das schwarze Focusrechteck wird immer angezeigt.

Und ... wo muß ich denn ansetzen, wenn ich diesen "dicken" Focusrahmen "schmäler" haben möchte? Der dicke schwarze Rahmen paßt irgendwie nicht in meine Programmoberfläche (vom Aussehen her). Hab alles etwas dezenter gehalten. :D

Aber, wie gesagt, kein Streß. Ich bin schon froh, daß Deine Komponente genau für meine Anforderung paßt.

Josef

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: fpspreadsheet und Rahmen

Beitrag von JosefKoller »

ach ja und noch was:

ich hab
MergeCells eingebaut (siehe Code)

Code: Alles auswählen

 
for i:=0 to dbmemo1.Lines.Count-1 do
  begin
    sWorksheetGrid1.Worksheet.WriteUTF8Text(i,0,dbmemo1.Lines.Strings[i]);
    sWorksheetGrid1.Worksheet.MergeCells(i,0,i,11);
  end;
 
Nach dem Speichern mittels stream und dem laden aus dem stream (über den Dateiumweg) ist das MergeCell weg.

Auch die Hintergrundfarbe einiger Zellen wird nicht mehr in silver angezeigt, sondern in einem gräulichen grobem Punktraster.
Auch die colwiths sind weg.
so steht es im Code:

Code: Alles auswählen

 
sWorksheetGrid1.Worksheet.WriteBackgroundColor(iLast+1,i,scSilver);
 


Ich häng dir mal 2 Bilder an, damit du siehst, was ich meine.

ciao

Josef
Dateianhänge
spreadsheet_vorher.jpg
spreadsheet_vorher.jpg (16.78 KiB) 3110 mal betrachtet
spreadsheet_nachher.jpg

wp_xyz
Beiträge: 5130
Registriert: Fr 8. Apr 2011, 09:01

Re: fpspreadsheet und Rahmen

Beitrag von wp_xyz »

Du speicherst im Excel2-Format, das konnte noch keine Hintergrundfarben, und ich glaube, auch kein Mergen. Die letzte Excel-Version mit binären Dateien war sfExel8 (in der fpspreadsheet-Nomenklatur). Oder nimm gleich die modernere Version sfOOXML (ab Excel2007), oder viele Leute nehmen statt Excel auch sfOpenDocument für LibreOffice.

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: fpspreadsheet und Rahmen

Beitrag von JosefKoller »

Hallo,

ich nehm auch Lebre Office.

Die Leute, die mein Programm bekommen, erstellen eben mit dem Programm so eine Auswertung. Dann soll diese Auswertung eben in eine Datei exportiert werden.

Diese Datei wird dann an eine zentrale Auswertungsstelle geschickt.

Die dort, haben mein Programm nicht. Sie bekommen eben nur die Datei. Gott weiß was die Leute dort an Software haben. Deswegen eben mein Gedanke, die niedrigste Excelversion zu wählen.

Ich glaub, daß Vernünftigste ist, beim Export einfach alle Format-Möglichkeiten anzubieten. Wenn ein Benutzer dann excel2 als Dateiformat nimmt, muß er halt mit den fehlenden Formatierungen leben.

Ich wüßt sonst nicht, wie ich das anders realisieren sollte.

Ciao

Josef

Antworten