Solved

Saving a user defined label layout for use later on

Posted on 2004-09-25
15
343 Views
Last Modified: 2010-04-05
Hi,
Newbie here.
I'm about to start developing a label printing program in which the user can create a label which will be used over and over again for printing item, supplier, customer labels etc.
The user will drop fields onto a label template then resize, adjust fonts and then assign a database field to the graphical field on the label layout.
So once this label layout has been created and saved the user will use the second part of the program to select, let's say, a list of customers from their SQL Server database. Then select the predefined label format and print a specified number of labels for the selected customers.

I guess my real issue is this.
I have a rough idea of how to do the first part of the program i.e setting up a label representation on screen that the user can modify to suit. I know how to do the second part i.e pulling user selected fields from the underlying database ready for printing. But how do I merge the two together:)

How do I save the layout from the first part in a way that I can easily access it in the second, assign the appropriate user selected database fields and print them in the right format.

Basically this is a very general question which will clear up some conceptual design issues for me before I start and any little tidbits would be appreciated. Clues on which components could be useful etc.

Anyway thanks heaps
Nathan



0
Comment
Question by:nathc
  • 10
  • 4
15 Comments
 
LVL 7

Expert Comment

by:sftweng
ID: 12153267
You should use the VCL components from the Data Access (e.g., TDataSet) and Data Controls (e.g., DBEdit, DBText, DBMemo) tabs and connect to your available datbase system. You might do this with the BDE (e.g., TTable) or ADO components or some other of your choosing. You might also use the Delphi Database Desktop to to define and manage the database. You'll find a number of example projects in %DELPHI%\Demos\Db.

You should also look at the Delphi Help "Designing Database Applications":

Database applications let users interact with information that is stored in databases. Databases provide structure for the information, and allow it to be shared among different applications.
Delphi provides support for relational database applications. Relational databases organize information into tables, which contain rows (records) and columns (fields). These tables can be manipulated by simple operations known as the relational calculus.
When designing a database application, you must understand how the data is structured. Based on that structure, you can then design a user interface to display data to the user and allow the user to enter new information or modify existing data.

The following topics introduce common considerations when designing a database application:

Using databases
      Database architecture
      Designing the user interface

0
 
LVL 4

Expert Comment

by:Delphian
ID: 12153783
You can get a text representation of
the label graphic object (assuming
that the objects inside are also Delphi
components, not just some kind of
"ghost" things) using the function
ObjectBinaryToText and its counterpart
ObjectTextToBinary.

See Delphi help for examples.
0
 
LVL 7

Expert Comment

by:sftweng
ID: 12153810
First time around I missed the point about user customization of the label. Delphian triggered a review with his approach concerning saving the graphic. I the case where you might use components from the "Data Controls", you might allow the user to use drag-and-drop and docking to tailor the format on the screen, saving the component's coordinates and characteristics into a separate profile file or database. You would save awat things like the component's top, left, width and height and it's colour. To get and set the latter, you could use a right-click popup menu to invoke a colour dialogue.
0
 

Author Comment

by:nathc
ID: 12153975
Hi guys,
I think I'm beginning to get a clearer picture.
So you're saying I can capture the characteristics of the components on the page as the user modifys them. e.g height, width, position etc. Is this saved to text and then converted to something the printer can recognise at a later time??
If I capture all of these properties as the user sets them, how do I save this template so I can load fields from the database into it for printing at a later time?
What sort of file should I be saving the template as??

Cheers for your help so far.
0
 
LVL 7

Expert Comment

by:sftweng
ID: 12154030
I suggest a TIniFile:

TIniFile stores and retrieves application-specific information and settings from INI files.

Unit

IniFiles

Description

TIniFile enables handling the storage and retrieval of application-specific information and settings in a standard INI file. The INI file text format is a standard introduced in Windows 3.x for storing and retrieving application settings from session to session. An INI file stores information in logical groupings, called “sections.” For example, the WIN.INI file contains a section called “[Desktop]”. Within each section, actual data values are stored in named keys. Keys take the form:

<keyname>=<value>

A FileName is passed to the TIniFile constructor and identifies the INI file that the object accesses.

A related object, TMemIniFile, works the same way as TIniFile, but buffers writes in memory to minimize disk access.

Tip:      You may choose to store information using the system registry instead of INI files. In this case, you can use TRegistryIniFile (which shares a common ancestor with TIniFile and so can be used in common code) or TRegistry.
0
 
LVL 7

Expert Comment

by:sftweng
ID: 12154037
As to printing, you could print the canvas of the form as a graphic image or you could use some other dynamically settable printing interface (e.g., QReport). It's probably much simpler just to print the canvas as a graphic image
0
 

Author Comment

by:nathc
ID: 12154058
Ah OK,
So I capture the properties of the different components on the label layout at the time the user saves it.
I write these to the INI file effectively storing an image of how the label should look.
When it comes time for the user to print labels using this layout I pull the details of the layout from the INI file.
I then insert the fields from the database into this layout and create a canvas to send to the printer??
I have a basic understanding of TCanvas but shall do some more research.
Is it easy to incorporate database fields into the canvas for printing??

I have used QReports recently for some static reports. I havn't discovered an easy way to allow users to layout the reports at runtime using this utility. I like the canvas idea.
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 7

Expert Comment

by:sftweng
ID: 12154070
I'd stick with just printing the canvas. It will show the form as it exists on the screen, so once you have placed the components, the printed output will be "WYSIWYG".

I'm going to send a small example in several minutes of configuring with the ini file, minus the database and printing linkage.
0
 
LVL 7

Expert Comment

by:sftweng
ID: 12154102
Here's a sample TIniFile program and a resulting ini file:

===================Program
unit uQ_21145118;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IniFiles, StdCtrls;

type
  TForm1 = class(TForm)
    NameLabel: TLabel;
    NameEdit: TEdit;
    CityLabel: TLabel;
    CityEdit: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  myIniFile : TIniFile;
  myIniFileName : String;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  try
    myIniFileName := 'MyIniFile.ini';
    myIniFile := TIniFile.Create(myIniFileName);
    with myIniFile do
    begin
      ReadString('Form','Caption','Form Name');
      ReadInteger('Form','Top',0);
      ReadInteger('Form','Left',0);
      ReadInteger('Form','Width',200);
      ReadInteger('Form','Height',200);
      ReadString('NameLabel','Caption','Name');
      ReadInteger('NameLabel','Top',2);
      ReadInteger('NameLabel','Left',2);
      ReadInteger('NameLabel','Width',50);
      ReadInteger('NameLabel','Height',40);
      ReadString('NameEdit','Caption','');
      ReadInteger('NameEdit','Top',NameLabel.Top);
      ReadInteger('NameEdit','Left',NameLabel.Left+NameLabel.Width+5);
      ReadInteger('NameEdit','Width',50);
      ReadInteger('NameEdit','Height',NameLabel.Height);
      ReadString('CityLabel','Caption','City');
      ReadInteger('CityLabel','Top',NameLabel.Top+NameLabel.Height+5);
      ReadInteger('CityLabel','Left',NameLabel.Width);
      ReadInteger('CityLabel','Width',50);
      ReadInteger('CityLabel','Height',40);
      ReadString('CityEdit','Caption','');
      ReadInteger('CityEdit','Top',CityLabel.Top);
      ReadInteger('CityEdit','Left',CityLabel.Left+CityLabel.Width+5);
      ReadInteger('CityEdit','Width',50);
      ReadInteger('CityEdit','Height',CityLabel.Height);
    end {with};
  except
    ShowMessage('Exception trying to read customization ini file '+myIniFileName);
  end {try};
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  with myIniFile do
  begin
    WriteString('Form','Caption',self.Caption);
    WriteInteger('Form','Top',self.Top);
    WriteInteger('Form','Left',self.Left);
    WriteInteger('Form','Width',self.Width);
    WriteInteger('Form','Height',self.Height);
    WriteString('NameLabel','Caption',NameLabel.Caption);
    WriteInteger('NameLabel','Top',NameLabel.Top);
    WriteInteger('NameLabel','Left',NameLabel.Left);
    WriteInteger('NameLabel','Width',NameLabel.Width);
    WriteInteger('NameLabel','Height',NameLabel.Height);
    WriteString('NameEdit','Caption',NameEdit.Text);
    WriteInteger('NameEdit','Top',NameEdit.Top);
    WriteInteger('NameEdit','Left',NameEdit.Left);
    WriteInteger('NameEdit','Width',NameEdit.Width);
    WriteInteger('NameEdit','Height',NameEdit.Height);
    WriteString('CityLabel','Caption',CityLabel.Caption);
    WriteInteger('CityLabel','Top',CityLabel.Top);
    WriteInteger('CityLabel','Left',CityLabel.Left);
    WriteInteger('CityLabel','Width',CityLabel.Width);
    WriteInteger('CityLabel','Height',CityLabel.Height);
    WriteString('CityEdit','Caption',CityEdit.Text);
    WriteInteger('CityEdit','Top',CityEdit.Top);
    WriteInteger('CityEdit','Left',CityEdit.Left);
    WriteInteger('CityEdit','Width',CityEdit.Width);
    WriteInteger('CityEdit','Height',CityEdit.Height);
  end {with};
end;

end.
===================Ini file
[Form]
Caption=Customizable Label Printer
Top=192
Left=282
Width=405
Height=192
[NameLabel]
Caption=Name
Top=32
Left=56
Width=28
Height=13
[NameEdit]
Caption=
Top=32
Left=128
Width=121
Height=21
[CityLabel]
Caption=CityLabel
Top=72
Left=56
Width=43
Height=13
[CityEdit]
Caption=
Top=72
Left=128
Width=121
Height=21
0
 
LVL 7

Expert Comment

by:sftweng
ID: 12154108
Oops - forget to assign the read values in the OnCreate event

e.g.,
  self.Caption :=  ReadString('Form','Caption','Form Name');
0
 
LVL 7

Expert Comment

by:sftweng
ID: 12154125
So here's what the FormCreate event should look like:

procedure TForm1.FormCreate(Sender: TObject);
begin
  try
    myIniFileName := 'C:\MyIniFile.ini';
    myIniFile := TIniFile.Create(myIniFileName);
    with myIniFile do
    begin
      self.Caption := ReadString('Form','Caption','Form Name');
      self.Top := ReadInteger('Form','Top',0);
      self.Left := ReadInteger('Form','Left',0);
      self.Width := ReadInteger('Form','Width',200);
      self.Height := ReadInteger('Form','Height',200);
      NameLabel.Caption := ReadString('NameLabel','Caption','Name');
      NameLabel.Top := ReadInteger('NameLabel','Top',2);
      NameLabel.Left := ReadInteger('NameLabel','Left',2);
      NameLabel.Width := ReadInteger('NameLabel','Width',50);
      NameLabel.Height := ReadInteger('NameLabel','Height',40);
      NameEdit.Text := ReadString('NameEdit','Caption','');
      NameEdit.Top := ReadInteger('NameEdit','Top',NameLabel.Top);
      NameEdit.Left := ReadInteger('NameEdit','Left',NameLabel.Left+NameLabel.Width+5);
      NameEdit.Width := ReadInteger('NameEdit','Width',50);
      NameEdit.Height := ReadInteger('NameEdit','Height',NameLabel.Height);
      CityLabel.Caption := ReadString('CityLabel','Caption','City');
      CityLabel.Top := ReadInteger('CityLabel','Top',NameLabel.Top+NameLabel.Height+5);
      CityLabel.Left := ReadInteger('CityLabel','Left',NameLabel.Width);
      CityLabel.Width := ReadInteger('CityLabel','Width',50);
      CityLabel.Height := ReadInteger('CityLabel','Height',40);
      CityEdit.Text := ReadString('CityEdit','Caption','');
      CityEdit.Top := ReadInteger('CityEdit','Top',CityLabel.Top);
      CityEdit.Left := ReadInteger('CityEdit','Left',CityLabel.Left+CityLabel.Width+5);
      CityEdit.Width := ReadInteger('CityEdit','Width',50);
      CityEdit.Height := ReadInteger('CityEdit','Height',CityLabel.Height);
    end {with};
  except
    ShowMessage('Exception trying to read customization ini file '+myIniFileName);
  end {try};
end;
0
 

Author Comment

by:nathc
ID: 12154136
Ahh nice, nice.
One more question sfteng.
When I build the canvas object using this information does it allow me to alter the look of the label. That is I don't want the label that prints to look exactly like the label image that the user creates on the screen. Different background etc.
Does TCanvas provide a lot of flexibility in adjusting the way the label actually prints??
This is the last question. I don't want you to have to write the actual program for me :)
0
 
LVL 7

Accepted Solution

by:
sftweng earned 250 total points
ID: 12154145
No, it would be difficult to change the canvas appearance (but no impossible). You might replicate the form into another invisible form, make the colour changes there and then print that one.
0
 

Author Comment

by:nathc
ID: 12154151
Thanks for all your help sfteng.
0
 
LVL 7

Expert Comment

by:sftweng
ID: 12154168
I'm happy to have been of assistance. I hope that you will enjoy using Delphi - it's the most powerful development system available for Windows, in my opinion, and does much to encourge good development habits.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
This video discusses moving either the default database or any database to a new volume.
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

24 Experts available now in Live!

Get 1:1 Help Now