Showing posts with label Delphi. Show all posts
Showing posts with label Delphi. Show all posts

Wednesday, 1 December 2010

A simple GUID generator function for Delphi

Here is a little code sample, that I run into the other day. The actual URL is here, but since the original site is now closed, I thought that I could save this posting on my blog as well.

If anybody running CodeGear RAD Studio 2007 ever wishes to play with GUID's then this function is a real must have, All credit goes to the original poster.

interface

function GUIDString: String;

implementation

uses ActiveX;
  
function GUIDString: String;
var
  Guid: TGUID;
  wsGuid: WideString;
begin
  Result := '';
  { create the 128 bit integer }
  if CoCreateGuid(Guid) = S_OK then begin
    { create a buffer of suitable size }
    SetLength(wsGuid, 80);
    { convert the 128 bit integer into a Unicode string }
    if StringFromGUID2(Guid, POleStr(wsGuid), 80) > 0 then
      { convert the Unicode to a String for output }
      Result := OleStrToString(PWideChar(wsGuid));
    end;  { if CoCreateGuid ... }
end;

Tuesday, 6 November 2007

BAPI / RFC with Delphi 2006 / 2007

Six months ago I wrote an article regarding how to install and use SAP's Active X components using Delphi 6. Here is the sequel regarding Delphi 2006 and 2007.

The basic idea is still the same you only need to install SAP Logon Control version 1.1, SAP BABPI Control Version 1.2 and finally import the SAP Remote Function Call Controll (Version 5.0) type library.

To complete the task in Delphi 2006, use the following procedure:

  1. Start Delphi 2006 and create a new package using the menu File → New → Package for Delphi Win 32.
  2. Save the package and the project using a name like SAPControls
  3. From the Delphi main menu select Component → Import Component.
  4. Locate the SAP Logon Control as show in the following image and click next
  5. In the following Screen just type SAP at the pallete page name ... and press next
  6. On the next screen select Add unit to Package radio item. ... and click Finish
  7. Repeat the previous steps and install the SAP BAPI Control and the Remote function type library. Unlike Delphi 6 you should get no compiler error messages.
  8. When you are finished, right click on the SAPControls package on the project manager window and select Install from the pop up menu.
  9. That does it. Create a new project and use the components of the new SAP pallete Category as you please.

Don't worry if you misplaced your components in an other category. You can drug them into any category you wish afterwards.

Thursday, 18 October 2007

Delphi: How to install BDE on a client machine

Suppose you have a Delphi application that access data using the Borland Database Engine (BDE) and you wish to deploy it on a user's client computer. If you compile the project without runtime packages and no BDE support is required, then merely copying the EXE file on the target computer is usually enough.

Now installing BDE on a client computer is performed as follows :

  1. Locate the file bdeinst.cab located in C:\Program Files\Common Files\Borland Shared\BDE.
  2. Open it using winZip or something equivalant.
  3. The .cab file contains only one file BDEINST.DLL. Extract this to the users client computer.
  4. Use the command regsvr32.exe bdeinst.dll from the command prompt to perform the installation.
  5. Run your application

BDE un-installation can be performed by folloowing these steps :

  1. Delete the folder containing BDE data
  2. Delete the BDEADMIN.CPL file in the Wiindows\System folder, in order to get rid of the control file applet
  3. Use regedit in order to delete the key HKEY_CURRENT_USER\Software\Borland\BDEAdmin
  4. Next locate HKEY_LOCAL_MACHINE\Software\Borland and delete the subkeys BLW32, Borland Shared and Database engine.
  5. Reboot your machine

Note : Having said all that I would like to give you an extract from the file bdedeploy.txt located at the BDE installation directory.

2. BORLAND-CERTIFIED INSTALLATION PROGRAMS
===========================================================
Borland products which include redistribution rights
include an Borland-certified install program, such as
InstallShield Express, to ensure proper installation and
uninstallation of your applications so that they co-exist
well with other applications which use the Borland Database
Engine (BDE) including those created with Visual dBASE,
Paradox, Delphi, and C++Builder.

Borland has also provided BDE and SQL Links installation
information to other install vendors such as Sax Software,
WISE Software, Great Lakes Business Systems (GLBS) makers
of the WISE install tool and Eschalon Development so that
their products can also be ensured to be fully compatible
with the BDE.

From time to time, Borland Software Corporation may, 
at its discretion, certify additional installation programs 
for use as the Borland Certified Install Program for this 
product.
  
Also check the Borland-sponsored announcement newsgroups:

  news:borland.public.announce
  news:borland.public.bde

3. BDE DEPLOYMENT (ALL DATABASE APPLICATIONS)
===========================================================
3.1 Deploying the BDE
---------------------
A Borland-certified installation program provides all
needed functionality and steps for redistributing the
Borland Database Engine (BDE), including:

  * Selecting files to redistribute
  * Determining final directory locations
  * Comparing versions of BDE files
  * Creation of BDE aliases
  
Follow the instructions of the particular installation
program used for specific steps to create an installation
program that includes the BDE.

Tuesday, 17 April 2007

SAP via Delphi Re-executing the same SAP function

After running the examples from BAPI / RFC with Delphi, I run into the following problem: Each time the Button2Click function was called the grid would show the results already displayed plus any data returned from SAP after the current call. A little bit of debugging showed that the table returned from the SAPFunctions object in statement Table := Funct.tables.item('DATA'), was the one that would not get initialized prior to Funct.call(). Aa I have no clues regarding the available methods of the table or the SAPFunctions object that would allow me to clear the table data before each call, I ended up rewriting the example performing the following changes.

  1. Create one connection object and retain it throughout the entire program session during FormCreate.
  2. Create and destroy a SAPFunctions object at each invocation of the ExecuteButtonClick() function. The way the table returned always has new data returned from SAP. This has been the only way I could avoid the problem of not initializing the returned table. Since I use similar code to perform data transfers between SAP and an other Oracle database at user defined intervals , this optin was more or less a one way.
The actual code of the get cost centers example now looks like this :
unit MainUni;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, OleCtrls, SAPLogonCtrl_TLB, Grids,
 StdCtrls, ComCtrls, ExtCtrls, Buttons;

type
 TFormMain = class(TForm)
   PanelLogin: TPanel;
   StatusBar: TStatusBar;
   ButtonExec: TButton;
   Grid: TStringGrid;
   SAPLogonControl: TSAPLogonControl;
   BitBtnClose: TBitBtn;
   procedure ButtonExecClick(Sender: TObject);
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
   Table, Funct, Connection : VARIANT ;
 public
   { Public declarations }
 end;

var
 FormMain: TFormMain;

implementation
{$R *.dfm}

Uses
  SAPFunctionsOCX_TLB;

procedure TFormMain.FormCreate(Sender: TObject);
  begin
     (* create a new connection object to be used
      * for all sessions
      *)
     Connection                  := SAPLogonControl.newConnection;
     Connection.System           := 'R3Q';
     Connection.Client           := '100';
     Connection.ApplicationServer:= 'sapqa_prd.shelman.int';
     Connection.SystemNumber     := '00';
     Connection.Language         := 'EN' ;
  end;

procedure TFormMain.ButtonExecClick(Sender: TObject);
  var
     txt : String;
     r : integer;
     SAPFunctions: TSAPFunctions;
  begin
     SAPFunctions := nil;

     // parameter "true" = SilentLogOn
     if Connection.LogOn(0, false) = true then
        try
           (* Create a new SAPFunctions obejct and
            * assign the existing connection to it
            *)
           SAPFunctions := TSAPFunctions.Create(Self);
           SAPFunctions.Connection := Connection;

           Funct := SAPFunctions.add('RFC_READ_TABLE');
           Funct.exports('QUERY_TABLE').value := 'CSKT';

           // attempt to call
           if not Funct.call then
              // called failed display the error in the statusbar
              StatusBar.SimpleText := Funct.Exception
           else begin
              // Call is successfull display returned data
              Table := Funct.tables.item('DATA');
              grid.rowCount := Table.rowcount + 1;
              grid.cells[0,0] := 'RecNo';
              grid.cells[1,0] := 'Client';
              grid.cells[2,0] := 'CostCent-No';
              grid.cells[3,0] := 'CostCent-Des.';
              for r := 1 to grid.rowCount -1 do begin
                 txt := Table.value(r,1);
                 grid.cells[0,r] := IntToStr(r);
                 grid.cells[1,r] := copy(txt,0,3);
                 grid.cells[2,r] := copy(txt,9,10);
                 grid.cells[3,r] := copy(txt,27,20);
              end;
           end;
        finally
           // close connection
           Connection.LogOff;
           // get rid of the SAPFunctions Object
           SAPFunctions.Free;
        end
     else
        StatusBar.SimpleText := 'Unable to login';
  end;

end.

Wednesday, 11 April 2007

BAPI / RFC with Delphi 6

A sad story with a happy end.

I wanted to write a small application that would update some Oracle tables based on data read from SAP using Delphi 6. Very soon I realized that it all came down to installing the various ActiveX components required for Delphi to connect to SAP, be able to execute functions and read the returned results.

And this is where the sad part of the story begins. Looking around at various sources I could find some instructions explaining how to perform the required installation but none of them seemed to be accurate enough or straightforward enough in order to produce the desired results. In my opinion the problem occurs because our German colleagues who provided the "how-to's" tried to translate the menus from their German Delphi to English and that caused the misunderstanding. Additionally, while following the directions provided I also run into compilations errors increasing my frustration. The following article provides my how to install SAP ActiveX controls on Delphi 6 and I hope to make it as clear as possible.

I have to admit that I owe everything to the guy who wrote and maintained the BAPI/RFC Programming with Delphi Page and to my good friend Marilena who found the page for me. The page has enough examples required in order for the average Delphi programmer to understand how to program the necessary communication. An other page that gives information regarding the pre-installation steps is this one found at SDN.

So here is the list of the steps I followed in order to install SAP ActiveX controls on my version of Delphi 6 If you are using Delphi 2006 then it you might beter have a look here.

  1. Create an additional package page to host the new components.
    1. Right click on the Delphi palette → Properties → Click the Add button.
    2. Type a name for the new page SAP will do just fine
    3. Use the Move Up and Move Down buttons to position the page at the correct position. Caution : Since the page will initially be empty it will not appear on the Delphi palette.
  2. Create an additional directory to hold the units for the new controls. In my case I created : C:\Program Files\Borland\Delphi6\Imports\SAPControls\.
  3. Go to main menu Component → Import ActiveX Control
    1. Select the SAP Logon Control Version 1.1 (wdtlog.OCX). The displayed class name should be TSAPLogonControl
    2. Select SAP as the Palette Page
    3. Change the directory of the unit file name to the new path created in the previous step.
    4. Click install. The first time select to create a new package, name it SAPControls and put it the path we are already using. The controls we will install next will be added to the package as well.
    5. Perform the same steps this time installing the TSAPBapiControl class from SAP BABPI Control Version 1.2
  4. Go to main menu Project → Import Type Library.
    1. Select SAP Remote Function Call Controll (Version 5.0). This will provide you with the TSAPFunctions, TFunction, TParameter, TExports, TImports, TStructure clases
    2. Click install and choose the SAPCOntrols package created previously.
  5. Press compile to compile the project. At this point I got many errors, but I will show you how to resolve them.
Many errors appear in functions with code like the following :
procedure TStructure.Set_Value(index: OleVariant; Param2: OleVariant);
 begin
   DefaultInterface.Set_Value(index) := Param2;
 end;
This should be corrected like this :
procedure TStructure.Set_Value(index: OleVariant; Param2: OleVariant);
 begin
   // DefaultInterface.Set_Value(index) := Param2;
   DefaultInterface.Value[index] := Param2;
 end;
The general error pattern is that there are unknown identifiers for functions of the form Set_XXX(i). These should be changed to indexed properties like XXX[i] Additionally I have had many functions not returning a value. The worst part is that the Delphi complier did not issue any warnings for some of them, so I had to look at each one separately. The worst case was the NewConnection method of the TSAPLogonControl class. The generated code was
function  TSAPLogonControl.NewConnection: IDispatch;
 begin
   DefaultInterface.NewConnection;
 end;
and it had to be corrected to
function  TSAPLogonControl.NewConnection: IDispatch;
 begin
   // had to add Result :=
   Result := DefaultInterface.NewConnection;
 end;
Failure to correct this results to all new Connections being returned null afterwards, making connections to R3 practically impossible. After you correct all the functions with warnings, you should be finished. Just press "Install" on the package dialog and you 're done The examples in BAPI RFC with Delphi page are good and they may get you started immediately. If I ever get any examples of my own I will post them in this page for future reference.