Announcement

Collapse
No announcement yet.

Excel OLE Suchen und ersetzen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Excel OLE Suchen und ersetzen

    Hey, wir haben bereits eine Wordkomponente, die zuerst mit Platzhaltern gefüllt werden kann und in einem 2. Schritt kann man bestimmte Platzhalter durch vordefinierte Werte ersetzen lassen.. Allerdings komm ich damit nicht so ganz zurrecht, da die zich Platzhalter dort schon per Schleifen ausgetauscht werden.
    Nun wollen wir das auch für Exceldokumente anbieten, also wollte ich es erstmal ganz minimal umsetzen aber es hängt beim Suchen/Ersetzen.

    Hier mal mein Quellcode bis zu meinem Problem:

    Code:
    procedure ExcelFuellen;
    var
      Excel : Variant;
      row, column: Integer;
    begin
    
      // Excel Objekt erzeugen
      Excel := CreateOleObject('Excel.Application');
    
      // Tabellen anlegen
      Excel.Application.SheetsInNewWorkBook := 2;                                  
      Excel.Workbooks.Add;
    
      // Tabellen umbenennen
      Excel.Sheets[1].Name := 'Tabelle 1';                                         
      Excel.Sheets[2].Name := 'Tabelle 2';
    
      column := 1;
    
      // Platzhalter einfügen
      for row := 1 to 5 do
      begin
      Excel.Sheets['Tabelle 1'].Cells[row,column].Value := Form1.Memo1.Lines[row-1];           // in Memo 1 steht ('Wert1:', 'Wert2:', 'Wert3:'... )
      Excel.Sheets['Tabelle 1'].Cells[row,column].ColumnWidth := '20,71';
      Excel.Sheets['Tabelle 1'].Cells[row,column+1].Value := Form1.Memo2.Lines[row-1];       // in Memo 2 steht ('[IA: Füllwert 1]', '[IA: Füllwert 2]', '[IA: Füllwert 3]'...)
      Excel.Sheets['Tabelle 1'].Cells[row,column+1].ColumnWidth := '20,71';
      end;
    
      // Inhalte ersetzen zB um Platzhalter zu füllen
      Excel.Cells.Replace(
        What := '[IA: Füllwert 3]',
        Replacement := 'Test',
        LookAt := xlPart,
        SearchOrder := xlByColumns,  <<< Hier brichts ab
        MatchCase := False,
        SearchFormat := False,
        ReplaceFormat := False
        );
    
      // Vorformatierungen
      Excel.Sheets['Mappe 1'].Cells[1,2].Style := 'Berechnung';
    
      // Zum Schluss öffnen und anzeigen
      Excel.Visible := true;
      Excel := unassigned;
    
      // Speichern und beenden ohne Excel zu zeigen
      Excel.ActiveWorkbook.SaveAs('C:\Users\khahn\Desktop\Delphi meets Excel\Test.xlsx');
      Excel.Quit; //Beendet Excel
      Excel := Unassigned;
    
    end;
    Wie ihr seht sind das erstmal nur kleine Rantaster an die Materie, denn ich hab vorher noch nie damit arbeiten müssen.
    Woran ich beim Suchen/Ersetzen scheiter sind die Parameter.

    Benutz ich beispielsweise SearchOrder := xlByColumns wirft mir Excel bei diesem Teil die Meldung 'Die Methode 'xlByColumns' wird vom Automatisierungsobjekt nicht unterstützt'. Mein Freund Google wusste darauf mal keine Antwort, deswegen wende ich mich mal an euch.

    Was muss ich tun damit ich einen bestimmten String auf einem Blatt oder im gesamten Dokument (über alle Blätter hinweg) ersetzen kann?

    Mit freundlichem Gruße
    Kev

  • #2
    Mein neuer Ansatz bis hierher: Ich selektiere einen bestimmten Bereich (dabei wird das sEnde später automatisch ermittelt) und möchte in dieser Selektion alle 'IA' durch 'XS' ersetzen.

    Code:
      sStart := '$A$1';
      sEnde  := '$B$5';
    
      Excel.Range[sStart, sEnde].Select;
      Excel.Selection.Replace(
        What:='IA',
        Replacement:='XS',
        LookAt:=xlPart,                    //unbekannter Bezeichner
        SearchOrder:=xlByRows,        //unbekannter Bezeichner
        MatchCase:=False,
        SearchFormat:=False,
        ReplaceFormat:=False
        );
    Jetzt haperts an den Bezeichnern. xlPart und xlByRows müssten noch irgendwie ersetzt werden. Hat da wer eine Idee?

    Mit freundlichem Gruße
    Kev

    Comment


    • #3
      Ja, zeichne im Excel ein Makro auf, während du händisch die gewünschten Aktionen ausführst.
      Analysiere dann den Makrocode und übernimm ihn in dein Projekt.

      Viel Erfolg!
      Tino
      Ich habs gleich!
      ... sagte der Programmierer.

      Comment


      • #4
        Hey,

        Der Makrocode:

        Code:
            
        Cells.Replace What:="IA", Replacement:="XS", LookAt:=xlPart, SearchOrder _
        :=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
        Umgeschrieben auf Delphi:

        Code:
          
        Excel.Cells.Replace(
            What          := 'IA',
            Replacement   := 'XS',
            LookAt        := xlWhole,
            SearchOrder   := xlByRows,
            MatchCase     := False,
            SearchFormat  := False,
            ReplaceFormat := False
            );
        Ich hab es auch schon probiert das ich als Parameter nur die Ergebnisse dort oben nehm aber da bleibt ja immer xlWhole und xlByRows übrig.

        Deklariere ich xlWhole und xlByRows als beispielsweise Variant, bekomm ich von Excel die Warnung 'Ungültiger Index', aber das ist ja klar, woher sollen diese variablen auch Werte haben.
        Interessant für mich wäre vllt wie ich Werte für diese Variablen finden könnte damit sie Sinn machen.

        Das Problem kann so leider nicht aus der Welt geschafft werden.

        Mit freundlichem Gruße
        Kev

        Comment


        • #5
          Hab mal ein wenig rumgespielt und habe einfach mal xlWhole und xlByRows als Konstanten gesetzt und ihnen ein paar Werte verpasst und siehe da Excel bewegt sich.

          Hier der Code:

          Code:
            Excel.Cells.Replace(
              What          := 'IA',         // in der Schleife ersetzen
              Replacement   := 'XS',         // in der Schleife ersetzen
              LookAt        := xlWhole,      // = 2 -> schaut in 2. Spalte
              SearchOrder   := xlByRows,     // = 1 -> geht alle Reihen in der Spalte durch
              MatchCase     := False,
              SearchFormat  := False,
              ReplaceFormat := False
              );
          Dadurch hat sich die Sache um xlByRows geklärt, allerdings bleibt xlWhole offen, da ich vorhabe das Dokument im Ganzen oder sogar mehrere Tabellen durchsuchen zu lassen.
          Wenn wer eine Idee für dieses 'Alles' hat, ich bin ganz Ohr.

          Mit freundlichem Gruße
          Kev

          Comment


          • #6
            Die Konstanten xlWhole usw. solltest Du eigentlich in der Type Lib finden. Wenn die Com Server Komponenten für Windows installiert sind auch unter [INSTALLPATH]/OCX/Servers je nach Version (Delphi und Windows)
            Achtung, die Konstanten können sich je nach COM Server Version ändern!
            Gruß, defo

            Comment


            • #7
              Musste gestern abrupt von der Arbeit weg und kam nicht mehr dazu weiterzumachen. Ich habe eben mal ein wenig gesucht und laut einiger Seiten sollte die Konstante xlWhole den Wert 1 haben, allerdings funktioniert das nicht.

              Da der Wert xlWhole irgendwie die Spalte darstellt habe ich eine andere Idee als Notfallplan wenn ich garkeine Lösung finden sollte: Finde die Zelle die am weitesten rechts ist und durchlaufe Suche/Ersetzen bis zur Spalte dieser Zelle. So sollte ich sichergestellt haben, das ich alles erwische (nach unten brauch ich ja zum Glück nicht schauen xlByRows macht ja was es soll).


              @defo: Ich habe mal gesucht ob ich die ComServer Komponenten installiert habe aber dem scheint nicht so. Welche TypeLib meinst du genau? Durch Vorinstallationen auf diesem Rechner sind in meiner Übersicht ein paar viele und nunja da ich noch Anfänger bin ist das ein wenig zu viel noch


              Edit: xlWhole muss einfach nur auf 2 stehen und er nimmt das gesamte Dokument. Ich Schelm hatte nur in der 2. Reihe eine Ladung Platzhalter und habe nun mal aus Spaß Spalte 3 & 4 gefüllt und siehe da, alles wird ersetzt so wie man es will.

              Mit freundlichem Gruße
              Kev
              Zuletzt editiert von Kev; 12.09.2012, 10:24. Reason: Lösung gefunden

              Comment


              • #8
                Ein hab ich noch. Zwar klappt jetzt alles für den aktiven Tab, jedoch könnt es durchaus sein, dass es Leute gibt, die auf allen Mappen Platzhalter ersetzt haben wollen. Da es mit dem aktiven Tab ja bereits klappt ist mein Ansatz nachdem ich auf dem ersten Tab alles ersetzt habe, den aktiven Tab zu wechseln und dann das Suchen/Ersetzen nochmals durchzuführen. Der Haken an der Geschichte ist dieser: Wie wechsel ich den aktiven Tab am dümmsten?

                Meine Idee: Doppelte For-Schleife, bei der sich die eine um die Tabs kümmert und die andere um das Ersetzen.

                Mein Code bis hierher:

                Code:
                var 
                  i, j : Integer;
                ...
                
                //Tabs durchschalten
                for i := 1 to Problem1 do
                begin
                    
                // Platzhalter austauschen
                    
                  for j:=0 to Form1.Memo2.Lines.Count do
                  begin
                    Excel.ActiveSheet.Cells.Replace(
                      What          := '{Platzhalter'+ IntToStr(j) +'}',
                      Replacement   := 'Test',
                      LookAt        := xlWhole,
                      SearchOrder   := xlByRows,
                      MatchCase     := False,
                      SearchFormat  := False,
                      ReplaceFormat := False
                      );
                  end;
                
                //Nächster Tab
                if not letzterTab (Problem2) then
                  nächsterTab (Problem3)
                 
                end;
                Problem 1 & 3 : Wie komm ich gescheiht an die Tabanzahl im geöffneten Dokument? Momentan hab ich mir eine Variable erstellt die mir das sagt, aber das geht bestimmt auch anders.
                Problem 2: Wie determiniere ich den letzten Tab (Index)?

                allgemeines Problem: Kennt irgendwer eine übersichtliche Dokumentation zu diesem Thema? Bisher hab ich mir alles krümelweise aus einzelnen Hilfthreads ziehen müssen. Die Dokumentation auf MSDN zu dem Thema, wo alles für VB, C# und Co abgehandelt wird war zwar schon hilfreich aber stark unübersichtlich.

                Mit freundlichem Gruße und einen schönen Feierabend wünschend
                Kev

                Comment


                • #9
                  Falls es nochmal wen gibt der sich dieser Probleme annehmen muss, gibt es hier ein wenig Hilfe meinerseits.

                  ErsetzenFunktion Grundschema:
                  Code:
                  Excel.Cells.Replace(                                    //Excel ist das OLE-Objekt > (CreateOleObject('Excel.Application');)
                        What          := **Was soll ersetzt werden?** (String),
                        Replacement   := **Durch was soll es ersetzt werden?** (String),
                        LookAt        := xlWhole, // = 1
                        SearchOrder   := xlByRows, // = 1
                        MatchCase     := False,
                        SearchFormat  := False,
                        ReplaceFormat := False
                        );
                  Diese Funktion gilt jetzt nur für das aktive Arbeitsblatt. Um alles Blätter einmal durchzugehen habe ich das ganze so gelöst:

                  Code:
                    sheet := 1;
                       
                       while sheet <= Excel.Worksheets.Count do
                       begin
                         
                         //Wechseln der aktuellen Mappe
                         Excel.Worksheets[sheet].Activate;
                  
                         //Warnungen aus
                         //damit Excel nicht rummeckert bei einigen Mappen, das es nix gefunden hat
                         Excel.Application.DisplayAlerts := False;
                  
                         //Ersetzen auf der aktuellen Mappe
                         Excel.Cells.Replace(
                           What          := **Was soll ersetzt werden?** (String),
                           Replacement   := **Durch was soll es ersetzt werden?** (String),
                           LookAt        := xlWhole, // = 1
                           SearchOrder   := xlByRows, // = 1
                           MatchCase     := False,
                           SearchFormat  := False,
                           ReplaceFormat := False
                           );
                  
                         //Warnungen an
                         Excel.Application.DisplayAlerts := True;
                  
                         sheet := sheet+1;
                       end;
                  
                      // 'Zurückspringen' auf die erste Mappe
                      Excel.Worksheets[1].Activate;
                  Um das ganze zu verbinden reichen 2 RadioButtons auf der Form und eine kleine If-Abfrage. So kann man immer aussuchen was wo ersetzt werden soll.
                  In diesem Sinne: Viel Spaß an alle mit einem ähnlichen Problem

                  Bei meiner Recherche bin ich auch hierdrauf gestoßen: ExcelConst.zip
                  Eine vollständige Liste aller in Excel benutzter Konstanten in einer .pas zusammengefasst mit Werten

                  Mit freundlichem Gruße
                  Kev
                  Zuletzt editiert von Kev; 19.09.2012, 10:16.

                  Comment

                  Working...
                  X