Ändern der Chart quellen mittels OLE

Von: , Frage gestellt am Mi, 25. Jan 2006

Ich möchte mittels Perl & der OLE Schnittstelle die Quellen eines existierenden Diagrammes ändenr, nur weiß ich nicht, wie ich den Pfad zum Diagramm finde?!?

Ich erzeuge das .xls File mit:
##################################################################
#Erstellen der Datei
##################################################################
use strict;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Excel';

my $Excel = Win32::OLE->new("Excel.Application");
$Excel->{Visible} = 1;

my $Book = $Excel->Workbooks->Add;
my $Sheet = $Book->Worksheets(1);
my $Range = $Sheet->Range("A2:C7");
$Range->{Value} =
[['Delivered', 'En route', 'To be shipped'],
[504, 102, 86],
[670, 150, 174],
[891, 261, 201],
[1274, 471, 321],
[1563, 536, 241]];

my $Chart = $Excel->Charts->Add;
$Chart->{ChartType} = xlAreaStacked;
$Chart->SetSourceData({Source => $Range, PlotBy => xlColumns});
$Chart->{HasTitle} = 1;
$Chart->ChartTitle->{Text} = "Items delivered, en route and to be shipped";
##################################################################

Nun füg ein 2. Skript periodisch Werte hinzu , was auch problemlos funktioniert.
Nur möche ich, dass das Diagramm immer die letzten z.B. 5 Werte darstellt, daher muss ich die Diagrammquellen mit ändern


Ich habe folgenden Ansatz:

my $Chart = $Excel->Charts->????????
#weil ich kann nicht add verwenden da ich damit ja ein neues erzeugen würde
$Chart->SetSourceData({Source => $Range, PlotBy => xlColumns});
#$Range, immer auf den richtigen Wert ändern und es würde funktionieren.

Nur wie kann ich das Chart auslesen????


Soweit so klar, was mein Problem ist??????

10 Antworten zu dieser Frage

  1. Antwort von nach 15 Tagen 0 hilfreich
    Re: Ändern der Chart quellen mittels OLE

    Hallo,

    ich habe zwar nicht dasselbe Problem, passt aber gut hierher.

    Bei folgende Zeilen ist mir die Funktionalität nicht ganz kalr :

    my $Range = $Sheet->Range("A1:C6");

    $Range->{Value} =
    [['Delivered', 'En route', 'To be shipped'],
    [504, 102, 86],
    [670, 150, 174],
    [891, 261, 201],
    [1274, 471, 321],
    [1563, 536, 241]];

    my $Chart = $Excel->Charts->Add;
    $Chart->{ChartType} = xlAreaStacked;

    $Chart->SetSourceData({Source => $Range, PlotBy => xlColumns});

    "my $Range = $Sheet->Range("A1:C6");"
    Diese Angabe ist unverzichtbar, da hier anscheinend auch indirekt festgelegt wird wie groß die X-Y-Matrix des Charts werden soll. Gleichzeitig werden hier aber auch die Zellen definiert in die unten angegebene Werte eingetragen werden.


    Ziel : Ich will eigentlich nur mit
    "$Range->{Value} =
    [['Delivered', 'En route', 'To be shipped'],
    [504, 102, 86],
    [670, 150, 174],
    [891, 261, 201],
    [1274, 471, 321],
    [1563, 536, 241]];
    "
    angeben welche Werte in einen Graph eingetragen werden sollen ohne gleichzeitig in die Zellen zu schreiben.

    Ich habe ein Excel-File wo die Werte in Zellen bereits stehen, die werden ausgelesen und sollen eben in Graphen nochmal dargestellt werden.

    Wo ist der Denkfehler, kann mir jemand Referenzen zu dem Thema nennen ?

    Gruß
    Mario

    • Antwort von nach 16 Tagen 0 hilfreich
      Verstehe ich das richtig?

      Du willst ein Chart erzeugen, welches Werte darstellt, ohne das die Werte irgendwo im Excelfile stehen????
      Das kann natürlich nicht funktionieren, da dies in Excel meines Wissens nicht vorgesehen ist!

      Hier mein Programm, mit ein paar Kommentaren!
      Ich erzeuge zufällig einen Wert schreibe diesen an das Ende mit Datum& Zeit Stempel ans Ende des Excelfiles und nehme die letzten 10 Werte für das Chart!
      Wenn du willst schicke ich dir auch das Excelfile dazu, damit du es ausprobieren kannst!

      Wobei ich auch festgestellt habe, dass OLE ein typisches Mikrosoft produkt ist, da es ab ca. 3000 Werte in der Liste (aufgrund des nicht optimal gewählten Suchalgorithmusses) sehr langsam wird. (Trotz periodischem aufrufes nur schreiben im 10 Sekunden takt)




      use strict;
      use Win32::OLE qw(in with);
      use Win32::OLE::Const 'Microsoft Excel';
      # Nummer Füllstand Zeit Datum

      Win32::OLE->Option(Warn => sub {goto Huho});
      #Huho ist die die Schreibfehler abfang funktion! Keine schöne Lösung, #aber sie funktioniertt!
      use Time::localtime;




      #Tämporäre Lösung, um immer anderen Füllstandwert zu haben
      my $fuellstand=rand(100);
      my $Zeile=3;

      my $test=3;
      retry:
      {
      my $Excel = Win32::OLE->GetObject('Hier/vollständigen/Pfad/angeben/Daten.xls');
      #$Excel->{Visible} = 1;

      my $Sheet = $Excel->Worksheets(1);

      #Lesevorgang um Ende festzustellen
      while(!($test == 0))
      {
      my $wert1='A'.$Zeile;
      my $wert2='D'.$Zeile;
      my $zeilenarray = $Sheet->Range($wert1 ,$wert1)->{'Value'};
      $test=1*$zeilenarray;
      $Zeile++;
      }
      $Zeile--;
      #print "Jetzt gehts ans schreiben:".$Zeile."\n";
      #schreibvorgang

      my $wert1='A'.$Zeile;
      my $wert2='D'.$Zeile;
      #print $wert1,"\t",$wert2,"\n";

      my $datum=localtime->mday().'.'.(1+localtime->mon()).'.'.(1900+localtime->year());

      my $zeit=localtime->hour().':'.localtime->min().':'.localtime->sec();
      #print $zeit."\n";
      my $Range = $Sheet->Range($wert1 , $wert2);
      $Range->{Value} = [ [$Zeile-2, $fuellstand, $zeit,$datum]];;


      # die letzten 10 Wärte in den Bereich des Diagrammes zu schreiben!
      my $linksoben = 'A'.($Zeile-10);
      my $rechtsunten='C'.$Zeile;
      my $Diagrammarray = $Sheet->Range($linksoben ,$rechtsunten)->{'Value'};
      my $ZielRange = $Sheet->Range("G3:I12");
      $ZielRange->{Value} = $Diagrammarray;
      $Excel->Save;
      exit;
      }
      Huho:
      {
      print "1 second delay, because of an error!\n";
      sleep(1);
      goto retry;
      }

      Ich hoffe ich konnte dir etwas weiterhelfen!

      • Antwort von nach 19 Tagen 0 hilfreich
        Re: Verstehe ich das richtig?

        Ich habe ein Excel-File wo die Werte in Zellen bereits stehen, die werden ausgelesen und sollen eben in Graphen nochmal dargestellt werden.
        Nein, das hast du wohl nicht richtig verstanden.

        Nochmal, die Werte werden schon durch ein anderes Perl-Script in das Excel-File geschrieben.

        Ich möchte nun mit einem eigenen Perl-Script diese Werte auslesen und mit einem Chart darstellen.

        Mein Problem ist, ich verstehe den Zusammenhang folgender Zeilen nicht: my $Range = $Sheet->Range("A1:C2");
        $Range->{Value} = [['Delivered', 'En route', 'To be shipped'], [504, 102, 86]];
        $Chart->SetSourceData({Source => $Range, PlotBy => xlColumns});
        In der ersten Zeile sage ich, die "Range" soll von A1:C2 sein.
        In der 2t gebe ich dann auf diese "Range" die Werte an.
        Das Script schreibt in diese Zellen, da stehen bei mir aber schon die Werte und sollen nur ausgelesen werden.

        Ich spiele schon mit dem Gedanken, das so zu akzeptieren und die Zellen, so wie sie sind auszulesen und mit ihren eigenen Werten zu überschreiben.

        • Antwort von nach 19 Tagen 0 hilfreich
          Re^2: Verstehe ich das richtig?

          Ja in der 2. Zeile werden die Werte geschrieben, lässt du diese weg, müssten deine Werte erhalten bleiben.
          In der 3. Zeile wird deinem Chart die Quelle zugewiesen; Die Quelle ergibt sich aus der Range.

          Soweit so klar????

          bzw. ich habe die Erfahrung gemacht, wenn ein Chart nur einmal erstellt werden soll, empfielt es sich dies manuel in Excel zu machen, und wenn es sich dynamsich änder soll, ändere ich die Werte in dem Bereich für das Diagramm!

          • Antwort von nach 20 Tagen 0 hilfreich
            Re^3: Verstehe ich das richtig?

            omg, da fehlen mir fast die Worte, so einfah des Rätsels Lösung ^^

            Ich habe genau andersherum erwartet my $Range = $Sheet->Range("A1:C2");
            weglassen zu können und mit $Range->{Value} = [['Delivered', 'En route', 'To be shipped'],
            [504, 102, 86]];
            expliziet die Werte angeben zu können.
            Naja, hab noch nie mit Excel-Perl gearbeitet und war halt n dummer Denkfehler.

            Dank dir
            MfG

  2. Antwort von nach 20 Tagen 0 hilfreich
    Re: Ändern der Chart quellen mittels OLE

    Ich möchte mittels Perl & der OLE Schnittstelle die Quellen
    eines existierenden Diagrammes ändenr, nur weiß ich nicht, wie
    ich den Pfad zum Diagramm finde?!?

    Nur wie kann ich das Chart auslesen????


    Soweit so klar, was mein Problem ist??????
    Soweit ich das verstanden habe kannst du mit folgenden Befehlszeilen auf ein bestehendes Worksheet zugreifen und das weiter bearbeiten : my $Book = $Excel->Workbooks->Open( $filename ); # open the file
    foreach my $Sheet (in $Book->Sheets) # loop through all sheets
    {
    foreach my $ChartObj (in $Sheet->ChartObjects) # loop all charts in :the sheet

    { my $savename = "$filename." . $count++ . ".$filter";
    $ChartObj->Chart->Export({
    FileName => $savename,
    FilterName => $filter,
    Interactive => 0});
    }
    Bin in der Perl-Hilfe darauf gestoßen, aber evtl. hast du dein Problem ja schon selbst gelöst.

    MfG
    Mario

    • Antwort von nach 20 Tagen 0 hilfreich
      Re^2: Ändern der Chart quellen mittels OLE

      Ich dachte ich hätte die Hilfe von oben bis unten durch, aber das ist auf jeden Fall auch keine schlechte Lösung!

      Ich hab es etwas umständlicher gemacht, indem ich dem Diagramm in einem eigenen Bereich die Werte in Excel zugewiesen habe, und diesen Bereich dynamisch mit Perl ändere!


      Aber trotzdem Danke!

  3. Antwort von nach 22 Tagen 0 hilfreich
    Re: Ändern der Chart quellen mittels OLE

    Hallo nochmal,


    habe noch ein paar Problemchen mit OLE/Charts.

    Am Besten ich beschreib mal was mein Script in Etwa macht.

    Die Daten im Excel-File bestehten im Wesentlichen aus aus vielen Spalten und Zeilen.......unglaublich oder ? ^^

    Diese sind in Daten-Blöcken zu je 2 Spalten strukturiert und sind eine bestimmte Anzahl Reihen groß. Es können mehrere Blöcke untereinander folgen, welche jeweils durch eine leere Zelle getrennt sind.

    Mein Script ließt nun Blockweise die Daten ein und schreibt die Daten pro eingelesenen Block.

    Es wird von Links oben, abwärts eingelesen, dann gehts 2 Spalten nach rechts usw.
    Je Block sollen die Daten in ein Chart eingetragen werden.
    Die untereinanderliegenden je in ein Sheet, mit farblich unterschiedlichen Graphen. Wenn eine neue Spalte beginnt wird ein neues Sheet erstellt.

    Soweit so gut.

    Mein erstes Problem ist, jeder Block einer Spalte überschreibt den Vorhergehenden.
    Ich schreibe mit my $Range = $Sheet->Range("A2:C7");
    $Chart->SetSourceData({Source => $Range, PlotBy => xlColumns});
    in ein Sheet.
    Wie schreibe ich in ein bestehendes Sheet ohne diese zu überschreiben ?

    2.Problem - Wie ändere ich die Farbe des Graphen ?
    3.Problem - Titel der Sheets ändern, standardmäßig heisst es ja "ChartXX".

    Ich finde in der Hilfe irgendwie keinen Ansatz.

    Need Help !

    Hilfreich wäre schon eine Referenz wo die ganzen Methoden, Member usw. von OLE ausführlich beschrieben sind, die Hilfe ist irgendwie ziemlich knapp gehalten.

    Gruß
    Mario

    PS: Falls meine Problembeschreibung unklar ist, bitte nachfragen.

    • Antwort von nach 28 Tagen 0 hilfreich
      Re^2: Ändern der Chart quellen mittels OLE

      Also es freut mich, dass andere auch mit dem selben Problem kämpfen! *gg*
      Ich habe das ändern der Werte eines Graphen umgangen, aber ich bin mir sicher das es geht!

      Ich weiß nicht ob du folgenden Link kennst:
      http://www.xav.com/perl/faq/Windows/ActivePerl-Winfa...
      Hier sind ein paar Beispiele für OLe auch dabei!

      Weiters zu der Sache mit dem Graphentitel:
      $Chart->{HasTitle} = 1;
      $Chart->ChartTitle->{Text} = "Items delivered, en route and to be shipped";

      Was ich am besten finde, man kann das Chart dann als jpg exportieren!
      Was hier weiter beschrieben ist, wie man durch alle Charts durch foreachen kann!
      use strict;
      use Win32::OLE qw(in with);
      use Win32::OLE::Const;
      use Win32::OLE::Const 'Microsoft Excel';
      $Win32::OLE::Warn = 3; # die on errors...

      my $filename = 'c:\\documents\\test.xls';
      my $filter = 'GIF'; # can be GIF, JPG, JPEG or PNG
      my $count = 0;

      my $Excel = Win32::OLE->GetActiveObject('Excel.Application')
      || Win32::OLE->new('Excel.Application', 'Quit'); # use the Excel application if it's open, otherwise open new
      my $Book = $Excel->Workbooks->Open( $filename ); # open the file
      foreach my $Sheet (in $Book->Sheets) { # loop through all sheets
      foreach my $ChartObj (in $Sheet->ChartObjects) { # loop through all chartobjects in the sheet
      my $savename = "$filename." . $count++ . ".$filter";
      $ChartObj->Chart->Export({
      FileName => $savename,
      FilterName => $filter,
      Interactive => 0});
      }
      }
      $Book->Close;

      ICh weiß, dass es immer noch nicht dein Problem löst, auf ein bestimmtes zuzugreifen, aber damit, kannst du einmal probieren dass du es beim 2. Durchlauf wieder hast dass Chart objekt, und kannst die gesamten Wertebereich ändern! wie man einzelln hinzufügt weiß ich leider auch nicht!
      Mir hat auch folgendes weitergeholfen:

      Where do I find documentation for the object models?
      The best way to learn about methods/properties would be through an OLE type browser if the documentation is unavailable.

      If you have Microsoft Excel or Microsoft Word available, go into the Visual Basic Editor (Alt+F11). Now you can open the object browser window (F2) and see what you find.
      --> Suche auch in VB Foren, und setzte den VB Code in Perl um!

      Was ich aber momentan leider nicht finde, ist die möglichkeit dem chart einen Namen (keinen Titel) zu geben! Wenn man dies tut, kann man bei einem neuerlichen auftruf wieder auf das objekt zugreifen!

      Glaubst du nicht, dass es in deinem Fall möglich ist Ein gesamtarray zu erstellen welches du dann mit $Range in:
      $Chart->SetSourceData({Source => $Range, PlotBy => xlColumns});
      zuweißt?????

      Ich hoffe dies hat die weitergeholfen! Bin auf deine Lösung auf jeden Fall sehr gespannt!



Keine passende Antwort gefunden? Jetzt eigene Frage stellen!