AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Excel Stringgrid in (vorhandene) Excel abspeichern
Thema durchsuchen
Ansicht
Themen-Optionen

Excel Stringgrid in (vorhandene) Excel abspeichern

Ein Thema von Moombas · begonnen am 17. Apr 2018 · letzter Beitrag vom 2. Mai 2018
Antwort Antwort
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
984 Beiträge
 
Delphi 6 Professional
 
#1

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 18. Apr 2018, 14:30
Hmm..

Um das hier mal abzukürzen...

Ein kleines Beispiel, basierend auf deinem Code, jedoch alle Excel-Sachen in eigene Unit verfrachtet und deutlich aufgeräumt..

In dem Beispiel wird ein Excel-Dokument (OpenDialog) geöffnet und das angegeben Sheet ein das Grid eingelesen.
Hierbei wird angenommen, das die erste ROW im Excel-Dokument die Header-Zeile ist.
(Musterdatei beigelegt)

Beim Speichern werden die Daten aus dem Grid ins Excel-Dokument geschrieben und dieses gespeichert.

Das eigentliche Schließen von Excel erfolgt erst im OnClose des Formulares.

(Erstellt mit D6)
Angehängte Dateien
Dateityp: zip Test_Excel_EditInStringGrid.zip (1,59 MB, 38x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von Moombas
Moombas

Registriert seit: 22. Mär 2017
Ort: bei Flensburg
525 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 18. Apr 2018, 15:02
Auch mit deiner Unit habe ich nun das Problem, das er die Zellinhalte der Worksheets durcheinander schmeißt. Das hatte ich zwischenzeitlich auch, weiß aber aktuell nicht woran es liegt.

Das Problem mit der Namensgebung lag an der Excel und konnte ich beheben.
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
491 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 18. Apr 2018, 17:18
Ähm... mal ne simple Frage: Wieso nicht einfach das StringGrid als CSV speichern?
Das lässt sich in Excel problemlos (sogar problemloser als XLS) öffnen, bearbeiten, speichern, und erzeugt keinen Overhead, der eh nicht notwendig wäre. Denn TStringGrids unterstützen doch eh nur Strings soweit ich weiß.
Dann hättest du fast einen "Einzeiler", und null Probleme, selbst wenn Excel nicht installiert ist oder nicht gefunden wird (oder die API sich geänndert hat).

Delphi-Quellcode:
procedure LoadCSV(Lines: TStrings);
var
  Index: Integer;
  Cols: TArray<string>;
  I: Integer;
begin
  StringGrid1.RowCount := Lines.Count;
  for Index := 0 to Lines.Count - 1 do
  begin
    Cols := Lines.Strings[index].Split([';', ','], '"', '"');
    StringGrid1.ColCount := length(cols);
    for I := 0 to StringGrid1.ColCount - 1 do
    begin
      StringGrid1.Rows[index].Strings[I] := Cols[I];
    end;
  end;
end;
Das wäre zum Laden. Das Speichern ginge noch einfacher...
Angehängte Dateien
Dateityp: zip csvsample.zip (3,49 MB, 10x aufgerufen)
Dennis
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 18. Apr 2018, 22:30
Auch mit deiner Unit habe ich nun das Problem, das er die Zellinhalte der Worksheets durcheinander schmeißt. Das hatte ich zwischenzeitlich auch, weiß aber aktuell nicht woran es liegt.
Wie sieht das "Durcheinanderschmeißen" denn aus? wird der erste mit dem 2, der 3. mit dem 4. Datensatz vertauscht? oder sind Spalten vertauscht?
Verschwinden leere Zellen?


Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von Moombas
Moombas

Registriert seit: 22. Mär 2017
Ort: bei Flensburg
525 Beiträge
 
FreePascal / Lazarus
 
#5

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 19. Apr 2018, 06:48
@Dennis07: Weil beim csv meines Wissens Formatierungen (also auch Farbvorgaben etc.) verloren gehen, die ich aber brauche. (Zu deiner Bemerkung mit den "strings": Das ist in Ordnung, ich möchte nur strings verwenden, selbst bei den Zahlen).

@K-H: Im Prinzip füllt er z.B. die erste Spalte nahezu komplett mit dem Wert aus der 2. Zeile. Wenn dort also "abc" steht, enthält nach dem speichern (beim einlesen ist dies noch korrekt) die erste Zeile in nahezu jeder Zeile "abc". Es hat ja schon mal funktioniert, daher wundere ich mich jetzt darüber.

Ich rufe es übrigens ohne OpenDialog auf, sondern direkt, da hier keine Dialoge etc. stattfinden sollen. Aber daran kann es ja eigentlich nicht liegen oder?

vorher (Eindeutige Zelleninhalte entfernt):
http://www.bilder-upload.eu/upload/4...1524118487.jpg

nachher (Eindeutige Zelleninhalte entfernt):
http://www.bilder-upload.eu/upload/b...1524118516.jpg

Es tauchen halt z.B. die Spaltenbeschriftungen innerhalb der Tabelle auch mehrfach auf, die Erste (und glaube zweite) Zeile ist auch noch korrekt, aber danach geht es halt los. Und alles was an Zahlen zu sehen ist, gehört halt eigentlich in die erste Spalte und zwar immer Zahl - 4 Felder frei - Zahl -... (in Excel sind hier 5 Zellen verbunden, das hat aber zwischenzeitlich einwandfrei funktioniert, stört also nicht). Aber den Zahlen fehlt hier die führende 0 (Die Zahlen müssen immer 4-Stellig sein, also theoretisch 0001 - 9999).

Geändert von Moombas (19. Apr 2018 um 07:32 Uhr)
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
984 Beiträge
 
Delphi 6 Professional
 
#6

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 19. Apr 2018, 08:03
Hmm...

Ich rufe es übrigens ohne OpenDialog auf, sondern direkt, da hier keine Dialoge etc. stattfinden sollen. Aber daran kann es ja eigentlich nicht liegen oder?
Nope, der Dialog gibt dir auch nur den Dateinamen zurück!

Es tauchen halt z.B. die Spaltenbeschriftungen innerhalb der Tabelle auch mehrfach auf, die Erste (und glaube zweite) Zeile ist auch noch korrekt, aber danach geht es halt los. Und alles was an Zahlen zu sehen ist, gehört halt eigentlich in die erste Spalte und zwar immer Zahl - 4 Felder frei - Zahl -... (in Excel sind hier 5 Zellen verbunden, das hat aber zwischenzeitlich einwandfrei funktioniert, stört also nicht). Aber den Zahlen fehlt hier die führende 0 (Die Zahlen müssen immer 4-Stellig sein, also theoretisch 0001 - 9999).
1.)
Hast Du dein XLS-Dokument mit meinem Testtool geöffnet und gespeichert?
Oder nur mit deinem Tool?

2.)
Was Excel aus den übergebenen Daten macht, darauf hast Du nur dann Einfluss, wenn Du die Spalten/Cells/Ranges vor übergeben der Werte expliziert formatierst.

Excel geht immer hin und 'versucht' die übergebenen Daten 'selber' zu interpretieren.
Und da können auch Formatierungen verloren gehen.
Gerade bei Strings mit Zahlen, denn eine '0001' ist als Zahl nunmal '1'.
Wenn Du die führenden 000 haben willst, dann muss Du das Feld explizit als Text definieren.

3.)
Haben deine Eingaben im Stringgrid vielleicht Tabs oder #0?
Dann könnte dies Excel fehlinterpretieren und Spalten verschieben.

4.)
Geh mal hin und formatiere deine Strings aus dem Grid mal (zum Testen) zu AnsiString, wenn Du sie in die Range packst.
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.740 Beiträge
 
Delphi 6 Enterprise
 
#7

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 19. Apr 2018, 08:05
Das könnte daran liegen, dass das Stringrid 0-basiert und Excel 1-basiert seine Zeilen und Spalten zählt. Betrifft dann diesen Bereich:

Delphi-Quellcode:
      Range := Worksheet.Range[RefToCell(1, 1), RefToCell(MaxCol, MaxRow)];
          if not VarIsNull(Range) then
          begin
            //Daten aus Grid holen
            Data := VarArrayCreate([1, MaxRow, 1, MaxCol], varVariant);
            for Row := 0 to Pred(MaxRow) do
            begin
              for Col := 0 to Pred(MaxCol) do
              begin
                Value := StringToVariant(StringGrid.Cells[Col, Row]);
                Data[Succ(Row), Succ(Col)] := Value
              end;
            end;
            //Daten dem Excelsheet übergeben
            Range.Value := Data;
            Range.Columns.AutoFit;
            Result := True;
Desweiteren kann es hier ggf. Sinn machen, für den Excel-Teil Used Range zu benutzen:
MaxCol := Min(StringGrid.ColCount, XLApp.Workbooks[ExtractFileName(ExcelE.Text)].WorkSheets[sheetname].UsedRange.Columns.Count);
MaxRow analog.
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von Moombas
Moombas

Registriert seit: 22. Mär 2017
Ort: bei Flensburg
525 Beiträge
 
FreePascal / Lazarus
 
#8

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 19. Apr 2018, 08:31
@Holger: mit deinem Tool in meinem integriert.
Delphi-Quellcode:
 if StringGridToXLS(FXLApp, DE_XLS, 'DE') then SaveExcel(FXLApp) else CloseExcel(FXLApp);
//...
@jumpy: Da ich die "extrahierte" Version von Holger nutze kommt die angesprochene Zeile so nicht mehr vor.


...ggf. mache ich es nachher testweise nochmal so, wie ich es ursprünglich gefunden hatte (https://www.delphi-treff.de/tipps-tr...l-exportieren/) und schaue dann ob ich es nochmal so hin bekomme, dann es dort raus zu nehmen.
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#9

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 19. Apr 2018, 08:32
Mit folgendem Schnipsel, kann man aus einem Stringgrid in eine Excel-Tabelle schreiben:
Delphi-Quellcode:
if forcestring then begin
      excel.activesheet.Cells.NumberFormat := '@';
  end;
  for i:=0 to sg.rowcount-1 do begin
    for j:=0 to sg.colcount-1 do begin
      zelle:=sg.cells[j,i];
      {----  Fehler 800A03EC  bei mehr als 255 Spalten!}
      excel.activesheet.cells(i+1,j+1):=zelle; {cells1..x/1..y }
    end;
  end;
(um den Spaltenfehler hab ich mich damals leider nicht mehr gekümmert)

Damit wird auch 007 übernommen.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von Moombas
Moombas

Registriert seit: 22. Mär 2017
Ort: bei Flensburg
525 Beiträge
 
FreePascal / Lazarus
 
#10

AW: Excel Stringgrid in (vorhandene) Excel abspeichern

  Alt 19. Apr 2018, 09:11
Es scheint ein Problem der Exceldatei zu sein.

Und zwar durch folgendes ausgelöst:

Exceldatei ("jungfräulich") mit den Daten gefüllt - ok
Exceldatei 1mal eingelesen - ok
Exceldatei 1mal gespeichert - ok (Eintragungen passen)
Exceldatei 2. Mal einlesen - Fehler -> Namenskonflikt (_Filterdatabase)
aus Exceldatei alle versteckten Namen entfernt mit folgendem Macro:
Code:
Sub EntferneNamen()
Dim i As Name
For Each DefName In ActiveWorkbook.Names
DefName.Delete
Next DefName
End Sub
Exceldatei 3. Mal einlesen - ok (Eintragungen passen, keine Fehlermeldung mehr)
Exceldatei 2. Mal speichern - alles durcheinander

Das Problem scheint also mit dem Namenskonflikt zu sein, denn wenn dieser nicht auftreten würde, bräuchte ich das Makro nicht auszuführen, welches scheinbar "zu viel" löscht und zu dem Fehler führt. -.-

Aktuell scheint die Lösung zu sein, Excel direkt noch zu speichern:
Delphi-Quellcode:
function StringGridToXLS(AXLApp : OleVariant; AGrid : TStringGrid; Sheetname : string):Boolean;
const
  xlCellTypeLastCell = $0000000B;
var
  Sheet: OLEVariant;
  MaxCol : Integer;
  MaxRow : Integer;
  Range : OleVariant;
  Data : OleVariant;

  Col : Integer;
  Row : Integer;
  R1,R2 : string;
begin
  Result := False;
  try
      //Worksheet auswählen
      if (Sheetname <> '') and HaveSheet(AXLApp, Sheetname) then
        begin
          Sheet := AXLApp.WorkSheets[sheetname];
        end else
          Sheet := AXLApp.WorkSheets[1];
      Sheet.select;

      // Der vorhandenen Daten im Grid, nicht der möglichen in Excel...
      MaxCol := AGrid.ColCount;
      MaxRow := AGrid.RowCount;

      if (MaxRow > 0) and (MaxCol > 0) then
      begin
        //Bereich auswählen
        R1 := RefToCell(1, 1);
        R2 := RefToCell(MaxCol, MaxRow);
        Range := Sheet.Range[R1, R2];
        if not VarIsNull(Range) then
          begin
            //Daten aus Grid holen
            Data := VarArrayCreate([1, MaxRow, 1, MaxCol], varVariant);
            for Row := 0 to Pred(MaxRow) do
            begin
              for Col := 0 to Pred(MaxCol) do
              begin
                Data[Succ(Row), Succ(Col)] := AGrid.Cells[Col, Row];
              end;
            end;
            //Daten dem Excelsheet übergeben
            Range.Value := Data;
            Range.Columns.AutoFit;
            Result := True;
          end;
      end;
  finally
    SaveExcel(AXLApp);
    Range := UnAssigned;
    Sheet := Unassigned;
    Data := Unassigned;
  end;
end;

Geändert von Moombas (19. Apr 2018 um 09:28 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:59 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz