Suche FreePascal Code für VBA Public Sub + Call

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Bernie110
Beiträge: 120
Registriert: Mo 10. Feb 2020, 17:43

Suche FreePascal Code für VBA Public Sub + Call

Beitrag von Bernie110 »

Hallo Zusammen,

um ehrlich zu sein weiss ich nicht nach welchen Stichworten ich suchen muss, daher vll eine total dumme Frage.
Ich habe verschiedene CodeSchnipsel die ich immer wieder an anderer Stelle aufrufen möchte.
In VBA macht man das über ein Public Sub und einem entsprechendem Call.
Geht so etwas auch in FreePascal ?
Hätte vll jemand ein Beispiel bzw nen Link für mich ?

Wäre echt nett. Danke im voraus für eure Hilfe
Lg Bernie

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von fliegermichl »

Code: Alles auswählen

 
function Sqr(Param1 : integer) : integer;
begin
 Result := Param1 * Param1;
end;
 
var : integer;
begin
 for i := 0 to 10 do writeln('Sqr von ', i, ' ist ', Sqr(i));
end;
 


Das definiert z.B. die function (sub) sqr, welche das Quadrat aus dem übergebenen Parameter berechnet.

Bernie110
Beiträge: 120
Registriert: Mo 10. Feb 2020, 17:43

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von Bernie110 »

fliegermichl hat geschrieben:

Code: Alles auswählen

 
function Sqr(Param1 : integer) : integer;
begin
 Result := Param1 * Param1;
end;
 
var : integer;
begin
 for i := 0 to 10 do writeln('Sqr von ', i, ' ist ', Sqr(i));
end;
 


Das definiert z.B. die function (sub) sqr, welche das Quadrat aus dem übergebenen Parameter berechnet.


Hi, danke für deine Antwort. Ich meinte jetzt nicht unbedingt eine Functions / Berechnungen. Ich meinte eher so Formatierungsgeschichten.
In VBA
kann man dafür eine Public_Sub "Beispiel" erstellen.
Da schreibt man seinen Code rein..
Und diesen Code kann ich dann von jedem Objekt ausführen lassen..
indem ich einfach CALL Beispiel eingebe.
Lg Bernie

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von Warf »

Code: Alles auswählen

procedure beispiel;
begin
// Ganz viel code
end;
 
...
// aufruf von beispiel
beispiel;

Bernie110
Beiträge: 120
Registriert: Mo 10. Feb 2020, 17:43

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von Bernie110 »

Hi, wenn ich das so mach,
dann erkennt er weder
FELDER_FARBEN
noch
AuftragsNR.Text

Code: Alles auswählen

procedure TFrm_AUFTRAEGE_ERFASSEN.FormShow(Sender: TObject);
begin
//FORM SHOW ===============================================================FORM SHOW
 
  Frm_AUFTRAEGE_ERFASSEN.Top := Frm_Hauptmenu.Top + 40;
  Frm_AUFTRAEGE_ERFASSEN.height := 470;
  LBL_INFO_AG.caption :=  LBL_AG_FirmenName1.Caption ;
  LBL_INFO_AUFTRAGSNUMMER.Caption := '  ' + AuftragsNr.Text + '  ';
  LBL_INFO_NL.Caption := NL.Text;
  LBL_INFO_AG.left := LBL_INFO_NL.Left +  LBL_INFO_NL.Width + 6;
  LBL_INFO_AUFTRAGSNUMMER.Left :=  LBL_INFO_AG.left + LBL_INFO_AG.Width + 10;
 
FELDER_FARBEN;
 
       // NL BEFUELLEN -----------------------------------
      NL.items.clear;
        with SQLQuery1 do
        begin
          close;
          SQL.Clear;
          SQL.ADD('select * from Stamm_NL where Aktiv = 1;');
          Open;
 
 
          SQLQuery1.first;
 
          while not SQLQuery1.Eof do
          begin
            NL.items.Add(SQLQuery1['NL']);
            SQLQuery1.next;
          end;
        end;
end;
procedure FELDER_FARBEN;
begin
 
   //AuftragsNR
      if AuftragsNR.Text <> '' Then
          begin
             AuftragsNR.Color := ClRed;
             AuftragsNR.Font.Color := ClWhite;
          end
         else
          begin
             AuftragsNR.Color := ClWhite;
             AuftragsNR.Font.Color := ClBlack;
          end;
end;

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von af0815 »

a) Die Procedure ist unbekannt, weil sie nicht früher deklariert wurde, sondern erst später. Das kann man auch über den Prozedurkopf mit angehängten forward machen (Stichwort forward-deklaration)
b) Die procedure FELDER_FARBEN ist ausserhalb der Forms deklariert, damit kann sie nicht auf Variablen des Forms direkt zugreifen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von Mathias »

a) Die Procedure ist unbekannt, weil sie nicht früher deklariert wurde, sondern erst später. Das kann man auch über den Prozedurkopf mit angehängten forward machen (Stichwort forward-deklaration)
Auf forward würde ich wen möglich verzichten. Besser ist es, wen man die procedure weiter oben schreibt.
Aus man will es wie in C/C++ machen, ist aber unübersichtlich.

Code: Alles auswählen

program Project1;
 
procedure Ausgabe(s:String);
begin
  WriteLn(s);
end;
 
begin
  Ausgabe('Hello World !');
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Bernie110
Beiträge: 120
Registriert: Mo 10. Feb 2020, 17:43

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von Bernie110 »

Hallo wie meint Ihr das die Procedur nach oben setzen.
Hab das versucht. Gleicher Fehler

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von Mathias »

So wäre falsch:

Code: Alles auswählen

program Project1;
 
begin
  Ausgabe('Hello World !');
end.
 
procedure Ausgabe(s:String);
begin
  WriteLn(s);
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von af0815 »

Ich gehe davon aus das du b)´nicht Erfüllt hast.

Du zeigst nirgends, wo deine Variablen definiert werden. Das ist bei Pascal ganz wichtig, da die Variablen unterschiedliche Sichtbarkeiten haben. Ich gehe davon aus, das du deine Variablen im Object (Class) TFrm_AUFTRAEGE_ERFASSEN deklrariert hast. Damit sind sie in der einfachen procedure FELDER_FARBEN nicht sichtbar, da diese zwar in derselben Unit nicht aber im selben Objekt ist.

Du musst dich von VBA lösen und dir die Grundlagen von Pascal und den Objekten ansehen.

https://de.wikibooks.org/wiki/Programmi ... Funktionen
https://de.wikibooks.org/wiki/Programmi ... l:_Klassen
https://de.wikibooks.org/wiki/Programmi ... uf_Klassen


BTW: Wenn du den Code von FELDER_FARBEN an den Platz einfügst, wo du die procedure aufruft, geht das überhaupt dort ?! Ich vermute du hast da ein Gemisch von Sichtbarkeiten erzeugt.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

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

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von wp_xyz »

So wie du Felder_Farben() deklariert ist das eine einfache Prozedur. In dieser erwähnst du aber Elemente, die zum Formular gehören, Klasse TFrm_AUFTRAEGE_ERFASSEN. Jede Instanz, die du zu dieser Klasse erzeugst, hat diese Elemente. Woher soll der Compiler nun wissen, welches gemeinst ist, wenn meherer solcher Fenster existieren?

Es gibt zwei Möglichkeiten, dieses Problem zu beseitigen: gib der einfachen Prozedur das Formular als Parameter mit auf den Weg, oder - und das ist der zeitgemäße, objekt-orientierte Weg - mache die einfache Prozedur zu einer Methode des Formulars. Das heißt: füge "procedure Felder_Farben" in den Deklarationsbereich des Formulars ein, wahrscheinlich in den Abschnitt "private", also

Code: Alles auswählen

type
  TFrm_Auftraege_Erfassen = class(TForm)
    AuftragsNr: TEdit;
    procedure FormShow(Sender: TObject);
  ....
  private
    procedure Felder_Farben;
  end;

Und dann muss auch noch bei der Implementierung der Prozedur der Klassenname vorangestellt werden:

Code: Alles auswählen

procedure TFrm_Auftraege_Erfassen.Felder_Farben;
begin
   //AuftragsNR
      if AuftragsNR.Text <> '' Then
          begin
             AuftragsNR.Color := ClRed;
             AuftragsNR.Font.Color := ClWhite;
          end
         else
          begin
             AuftragsNR.Color := ClWhite;
             AuftragsNR.Font.Color := ClBlack;
          end;
end;

Nun kennt die Prozedur Felder_Farben den Bezeichner AuftragsNr, da die Prozedur genauso wie AuftragsNr zum selben Objekt gehören.

In FormShow machst du einen beliebten Anfänger-Fehler: Du verwendest den Namen der Formularvariablen Frm_Auftraege_Erfassen im Code der Klasse TFrm_Auftraege_Erfassen. Eine "Klasse" ist eine Art Schablone, der Code dieser Schablone muss aber immer funktionieren, egal wie die Klasse heißt. Dein Code dagegen setzt voraus, dass das Formular wirklich Frm_Auftraege_Erfassen heißt. Was ist, wenn du es aus irgendeinem Grund zweimal brauchst und der zweiten Instanz einen anderen Namen geben musst, oder wenn du schreibfaul bist, und das Formular nur "F" nennst? Daher folge dieser Regel: Lasse den Namen des Formulars einfach weg (oder verwende den Bezeichner "self") - das Formular weiß selbst, wie es heißt.

Code: Alles auswählen

procedure TFrm_AUFTRAEGE_ERFASSEN.FormShow(Sender: TObject);
begin
//FORM SHOW ===============================================================FORM SHOW
 
  //Top := Frm_Hauptmenu.Top + 40;   /// GEFÄHRLICH!!! Das macht irgendwann Probleme, wen es Frm_HauptMenu nicht gibt!
  Height := 470;
  LBL_INFO_AG.caption :=  LBL_AG_FirmenName1.Caption ;
  LBL_INFO_AUFTRAGSNUMMER.Caption := '  ' + AuftragsNr.Text + '  ';
  LBL_INFO_NL.Caption := NL.Text;
  LBL_INFO_AG.left := LBL_INFO_NL.Left +  LBL_INFO_NL.Width + 6;
  LBL_INFO_AUFTRAGSNUMMER.Left :=  LBL_INFO_AG.left + LBL_INFO_AG.Width + 10;
 
  FELDER_FARBEN;
...
end;

Wie in dem Code gekennzeichnet, habe ich noch ein Problem mit der 1. Zeile: Top := Frm_Hauptmenu.Top + 40. Ich nehme an, dass Frm_Hauptmenu ein anderes Formular ist, wahrscheinlich eins, aus dem heraus Frm_Auftraege_Erfassen, aufgerufen wurde. Das ist dasselbe Problem: TFrm_Auftraege_Erfassen funktioniert nicht mehr, wenn Frm_HauptMenu nicht (mehr) existiert. Es ist eine grundlegende Herangehensweise der objekt-orientierten Programmierung, dass solche Annahmen nicht gemacht werden dürfen. Entferne diese Zeile aus TFrm_Auftraege_Erfassen.FormShow und füge sie dort ein, bevor es von Frm_Hauptmenu angezeigt wird. Also, wenn Frm_Hauptmenu z.B. einen Button hat, der das andere Formular öffnet, dann sollte dieser Code dort im OnCLick stehen:

Code: Alles auswählen

procedure TFrm_Hauptmenu.Button1click(Sender: TObject);
begin
  Frm_Auftraege_Erfassen.Top := Top + 40;   // das 2. "Top" ist das von TFrm_HauptMenu !
  Frm_Auftraege.Show;
end;

Bernie110
Beiträge: 120
Registriert: Mo 10. Feb 2020, 17:43

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von Bernie110 »

Klasse wp_xyz ! Verständlicher kann man es nicht erklären !! Danke !

Schön, dass du den 2ten Teil gleich mitabwickelst :-)
Das deutest du alles richtig.

Das ist mir heute erst aufgefallen, dass dadurch Probleme enstehen, da ich
das Frm_Auftraege_Erfassen mehrmals aufrufen wollte. Und da hatte ich noch das Form drin

Code: Alles auswählen

//Frm_Auftraege_Erfassen.Top := Frm_Hauptmenu.Top + 40;

Anfängerfehler :mrgreen: richtig.. Aber ich kann nur so.. ich muss drauflosprogrammieren und fehler machen....sonst lern ich Pascal nie :mrgreen:

Super werde ich so machen !! Danke und Danke @all
Frohe Ostern Zusammen ! Bleibt gesund !
Lg Bernie

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Suche FreePascal Code für VBA Public Sub + Call

Beitrag von fliegermichl »

In Pascal gibt es globale Variablen, lokale Variablen und Objektfelder.

Beispiel:

Code: Alles auswählen

 
program global;
var g1 : integer;
 
procedure test1;
begin
 g1 := 4;
end;
 
begin
 writeln(g1); // Gibt irgendwelchen Unfug aus weil g1 nicht initialisiert wurde
 g1 := 1;
 writeln(g1); // Gibt 1 aus weil die globale Variable jetzt initialisiert wurde
 test1; // Ruft die procedure (sub) test1 auf
 writeln(g1); // Gibt 4 aus weil die globale Variable in der Unterroutine mit 4 befüllt wurde. Gaaaaanz schlechter Programmierstil.
end.
 


So weit das irgendwie geht, sollte man auf globale Variablen verzichten. Dadurch entsteht bei größeren Programmen ein unentwirrbarer Spaghetti Code.

Dann kommt noch der Scope dazu. Man kann eine globale Variable sowie eine lokale Variable gleichen Namens deklarieren. Beispiel:

Code: Alles auswählen

 
program global_lokal;
var g1 : integer; // globale Variable
 
procedure test1;
var g1 : integer; // lokale Variable mit dem gleichen Namen wie die globale, ist aber nur innerhalb der procedure test1 gültig
begin
 g1 := 4;
 writeln(g1); // gibt 4 aus
end; // ab hier ist die lokale Variable g1 nicht mehr existent
 
begin
 g1 := 1; // Hier ist der Scope (Gültigkeitsbereich) die global deklarierte Variable g1
 writeln(g1); // gibt 1 aus
 test1; // ruft die procedure test1 auf, die aber lediglich die lokal deklarierte Variable befüllt
 writeln(g1); // gibt wieder 1 aus, weil die lokal in test1 deklarierte Variable hier nicht existiert
end.
 


Bei Objekten (Klassen) ist es dann noch etwas spezieller. Hier wird bei der Klassendefinition sozusagen nur das Verhalten der Klasse definiert. Jede erzeugte Instanz davon, hat aber ihre eigenen Daten aber dennoch Zugriff auf globale Variablen. Das ist dann die totale Katastrophe.

Code: Alles auswählen

 
program objekte;
 
var g1 : integer;
 
type
 TMyClass = class
  g1 : integer;
  procedure Printg1;
 end;
 
procedure TMyClass.Printg1;
begin
 writeln(g1); // Hier wird jetzt der Inhalt der Instanz von TMyClass ausgegeben (also 1 bei a und 2 bei b)
end;
 
var
 a, b : TMyClass;
begin
 g1 := 1;
 a := TMyClass.Create;
 a.g1 := 2;
 b := TMyClass.Create;
 b.g1 := 3;
 writeln(g1)// Ausgabe 1 der globalen Variable g1
 writeln(a.g1)// Ausgabe 2 der Instanz a von Klasse TMyClass
 b.printg1; // Ausgabe 3, weil die Methode printg1 der Instanz b von TMyClass aufgerufen wurde.
end;
 


Mir fällt gerade auf, daß diese Zusammenhänge recht schwierig zu erklären sind.

Antworten