Diese Seite mit anderen teilen ...

Informationen zum Thema:
Forum:
WinDev Forum
Beiträge im Thema:
29
Erster Beitrag:
vor 5 Jahren, 2 Monaten
Letzter Beitrag:
vor 5 Jahren, 2 Monaten
Beteiligte Autoren:
Yogi Yang, Al, Peter Holemans, Frans, Alexandre Leclerc, Piet van Zanten

Want advise on Programming in WD for a new project that is coming up [[5]]

Startbeitrag von Yogi Yang am 13.05.2013 10:39

I am basically hoping that this thred will be interactive as I have many quries and I am hoping that for some of the queies I will be shown some small code snippets to help out. As most of the quries are interelated I will ask the basic questions and then follow up with more questions.

I hope forums moderators will not have any problems with this thread.

I am asking for this advise for the new project that I am going to embark upon soon.

Ok - here is my request for good advise:

I have completed two small size projects where were reprogramming of existing software. This reprogramming went quite smooth. But while programming in WD if felt that I am spending more time connecting each control on a form(window) to respeceive data file and field.

I also feel that the Description dialog box is a bit too much to navigate and there are no short cut keys to say switch from General tab to Style tab or GUI tab. (I may feel like this about Description dialog as I my programming background is VB and Delphi dev tools and am used to VB's and Delphi's Property Palettes for setting properties of a selected controls).

Anyways, so I feel that instead of doing this would it be adviseable to say, build window with required controls and then link those controls to a file and its fields when the window loads.

What do the long term experinced WD developers think of this?

Antworten:

Hi YY,

If your controls are connected to queries/data files directly. You can drag and drop them from the project browser to the window directly. In this case they will be linked immediately and automatically.

If you're doing OO and the controls are linked to class instance members, then unfortunately there is no other option than to map them manually one by one. It would be great if PCSoft would foresee a point and click mechanism to get this done in a more productive way.

Best regards,

Peter H.

von Peter Holemans - am 13.05.2013 10:48
Hello Yogi

There is a pane that may supply what you are looking for. From the Main IDE window
Display > Toolbars > Panes > Modifier

If you do as Peter suggests, and drag the file fields onto the window from the explorer pane, the filetoscreen() command will autoload all the connected controls as the window opens and ScreenToFile will pass the information back to the file. You need separate ScreenToFile() and FileToScreen() commands if you use more than one file to palce controls on a screen. All the fields/controls do not have to be visible. It is quite handy to place controls linked to file fields, offscreen and have actions on the screen write data into them and then that data is automatically handled by the screen/file commands. It is quite amazing what you can do in Windev with almost no code.

It might be useful to investigate all the available progamming panes in the display option.

Keep in mind that Windev offers a very unique programming method so don't try and bend it into being like your VB or Delphi tools because you will become quite frustrated with it - "Use the force"

Regards
Al

von Al - am 13.05.2013 12:00
Hi Yogi,

There is a property-like panel available (http://doc.pcsoft.fr/en-US/?2027006). But I prefere the Description dialog (7 tabs) - you get used to it after a while.

My advice would be to use databinding wherever possible.

Depending of the scope of your project my second advice would be coding it in 3-tiers, making databinding on classes and from classes to files. For this we made ourselfs a super (yet very lightweight) DBAccess class, from which all file-class inherit, that handles all the stuff: read (from file or query), write to file but only the members that actually changed (so two users in the same data record can simulteanously change different data with no conflict - otherwise the last write is the one taken), work with integer or string keys, detect modifications, handle in-memory data management and deletions (when having data in tables not yet saved, and also must join the data with other data using temporary memory IDs - unless you use GUID), pre-/post- save/delete events, locks if required, etc.

This allows cool stuff like continuous saving as the use types data in a form or on the contrary save only at the end on a given action after many complex modifications. Everything is managed in memory and dumped to file when required. Finally you can develop a webservice with no efforts because you load the class on server then simply send back to class on a client consumer. Vice-versa for saving. Etc.

So well planned 3-tiers can save you a lot of time down the road on big projects. With this architecture, no application triggers are required at all because all files are managed by classes. Then we have a third level for "rules" classes. Like one for orders where it needs header files (a class for that file exist) and detail files (a class for that one too) to work in sync. Etc. Finally all is written using transactions where required. So we are always in sync whatever happens.

Maybe this can give you some ideas. Coding in OO and 3-tiers requires a bit of experience with software architecture and with WinDev to work well. It will not be 10 times faster when you start but you also get it back down the road. It really depends the needs of your projects. Traditionnal coding can work very well too, using triggers, etc.

Best regards,
Alexandre Leclerc

von Alexandre Leclerc - am 13.05.2013 12:37
Hi Yogi,

Indeed the form type windows are the most boring types.
I never used the RAD, but for many years now I'm using the same routine. It may be outdated, but it works for me and I'm too lazy to develop a new one.
For the code I'm using a very simple class. (see below)
The following process will take about 5 minutes to build a new form window, once you have one or more to start from.
I take an existing form window that looks the most like my new window to be. (type and number of controls)
- save it as a new name
- add or delete controls as needed
- change the captions as needed
- change all the links
- change the references to the main file or query.

Well you said you'd like to see some code snippets, here they are:

In the project global declarations I define three contants:
const_Creation=1
const_Modif=2
const_Copy=3 (used to create a new record using the items of an existing one)

In the form window/page Global declarations:
PROCEDURE win_MyForm_fic(nEditMode=const_Creation) 
//the _fic extension is a very old Windev convention for form type windows, fichier is French for file)
bOK is boolean
Thisform is object clVZform("MyFileorQueryName",nEditMode)
//e.g. Thisform is object clVZform("qry_Customer",nEditMode)

The OK (save) button:
ScreenToFile()
//here you can do some additional stuff to the file buffer if needed and some validation stuff.
IF Thisform:SaveForm() THEN
bOK=True
Close()
END
The Cancel button:
Close()

In the window closing code:
RESULT bOK

Finally the class:

clVZform is Class
PUBLIC
m_sFileName is string
m_nCallMode is int
END

PROCEDURE Constructor(sFileName,nCallMode)
:m_sFileName=sFileName
:m_nCallMode=nCallMode
IF nCallMode=const_Creation THEN
Reset(True)
HReset(sFileName)
ELSE
FileToScreen()
END
FUNCTION VZform::SaveForm()
IF :m_nCallMode=const_Modif THEN
HModify(:m_sFileName) // Modification
ELSE
HAdd(:m_sFileName)
END
IF HErrorLock() THEN
Error("File locked by another user.","Please try again or cancel your input.")
RESULT False
END
IF HErrorDuplicates() THEN
Error("Duplicate error.")
RESULT False
END
IF HErrorIntegrity() THEN
Error("Integrity error.",HErrorInfo())
RESULT False
END
RESULT True

To call the form (for modification or copy the filebuffer needs to point to the correct record):
//creation:
IF Open(win_MyForm_fic) THEN
//modification
IF Open(win_MyForm_fic,const_Modif) THEN
//copy
IF Open(win_MyForm_fic,const_Copy) THEN
....
//input ok
ELSE
//error or input cancelled
END


Once you have some windows like this it is very easy to create a new one based on one of them: just change the links and the name of the file in the class parameter. An easy way to copy a link is using F4 on the control after you selected a link on a a previous control. Then you don't need to scroll, just click an adjacent item.

Regards,
Piet

von Piet van Zanten - am 13.05.2013 14:43
Al,

Thanks for the tips.

As always they are invaluable. :)

von Yogi Yang - am 13.05.2013 15:29
Peter,

I am not doing OO in WD. But my original style of working (in VB and Delphi) is to define various routines (in amodule) that will be responsible for loading data in controls, saving data from controls, etc.

So if I want to load a drop down combo box with data that comes from a file which contains master data are there any possibilities of loading the data with their ID directly in a combo box?

What is faster in loading grids with data - directly connecting grids to data file or loading using code?

Finally is it possible to add custom properties to windows and access them?

Thanks for your inputs.

von Yogi Yang - am 13.05.2013 15:34
Hello Yogi

I program in much the same manner as Piet in terms of reusing windows and modifying them and it works well. The only change is that all the standard routines that Piet does in OO I do with procedural code.

I have a centralised description process that supplies all sorts of descriptions to my apps and in the drop down combos, I use Glink() to provide the hidden primary key value that is then extracted out for inclusion as a foreign key in the file where it is used.

With the screen tables (Grids) data fill will always be quicker with large files but for small files up to say, a thousand records there is not much difference even if you hand fill the table from a read loop, providing your indexes suit the task


Regards
Al

von Al - am 13.05.2013 22:58
Thanks everyone for your inputs and advise.

Here is am image for the software that I am planning to convert.
[attachment 336 2013-05-14_093019.jpg]

Would it be possible to format Table Control to show data in something like manner if I bind it to data file?

TIA

Yogi Yang

von Yogi Yang - am 14.05.2013 04:21
Hello Yogi

You could start by dragging the file - not the fields- onto a window from the explorer pane. This will open up a table creation wizard and if that gives you a workable solution then everything is done because the table cells will be linked to the data file. It looks like your example has groups so you may be able to achieve that with the breaks that can be setup in the "Content" tab of the table editor. How successful that is, will depend on the index keys you have because they will determine the breaks you can setup

If you fill the table by hand from a read loop than you will have more freedom to set breaks and will have more sort and search options available in the columns. I think this would also apply with a data bound table set to "Loaded in Memory".

Regards
Al

von Al - am 14.05.2013 04:40
Hi Al,

Actually the data comes from multiple files. I did try to get the data using one single SQL query but could not get the data as requied.

Here are the original 3 SQL Queries that are generated dynamically and the data is extracted and inserted.

Quote

SELECT * FROM RoomMaster WHERE [rm_ghm_id] = 1 ORDER BY rm_is_reserved, rm_is_ac, rm_num

SELECT * FROM BookingForm WHERE bf_ghm_id = 1 AND bf_rm_id = 5 AND '2013-03-26' BETWEEN [BookingForm].[bf_from_date] AND [BookingForm].[bf_to_date] AND bf_cancelled = 0

SELECT [BookingForm].[bf_id],[DonationReceipt].[dr_id] AS [DonationID], [DonationReceipt].[dr_num] AS [DonationNum], [DonationReceipt].[dr_donation_amount], [DepositReceipt].[dr_id] AS [DepositID], [DepositReceipt].[dr_num] AS [DepositNum], [DepositReceipt].[dr_deposit] FROM [BookingForm] LEFT JOIN [DonationReceipt] ON [BookingForm].[bf_id] = [DonationReceipt].[dr_bf_id] LEFT JOIN [DepositReceipt] ON [BookingForm].[bf_id] = [DepositReceipt].[dr_bf_id] WHERE [BookingForm].[bf_id] = 10


von Yogi Yang - am 14.05.2013 05:18
Hello Yogi

I am guessing that one of the queries is supplying the main record and the other two are used to provide additional info into one or more columns per main record ?

If that is the case, then you probably have to read through the main data set and build the table line by line. - If you could get it into one query result then you could use FileToMemoryTable to load it straight into the table.
All the Windev File commands are available to a query so..


Hreadfirst(MainQuery)
While not Hout(MainQuery)
HreadSeekFirst(SecondQuery,Index,KeyFromMainQuery)
HreadSeekFirst(ThirdQuery,IndexKey,KeyFromMainQuery)
TableAddline(Table,Fields fromMainQuery,FieldsFromSecondQuery,FieldsFromThirdQuery)
HreadNext(MainQuery)
End //While not Hout(MainQuery)


There is a bit more to it than that but that's the principle of loading a table using a read loop.
You will see that for this approach, it may be better sometimes not to bother with queries 2 & 3 and just refer to the files for the other data as this is sometime quicker than building the query first.
I am sure this will start a host of replies with better/different methods :)


Regards
Al

von Al - am 14.05.2013 07:11
Hi Al,

Thanks,

Yes you gussed right. This is regarding a room booking system for tourists for a GuestHouse.

Quote

SELECT * FROM BookingForm WHERE bf_ghm_id = 1 AND bf_rm_id = 5 AND '2013-03-26' BETWEEN [BookingForm].[bf_from_date] AND [BookingForm].[bf_to_date] AND bf_cancelled = 0


If you have observed the second query here I have used. It is unusual (at least that is what many a developers have told me). Here I am using a Data in between clause I am using field names!

Does WD and HF support such quries or have we to do some work arounds here?

von Yogi Yang - am 14.05.2013 07:52
Hi YY,

Yes you can, these become just parameters in your query.
Query:
SELECT A, B, C, D FROM T1 WHERE E BETWEEN {pFromDate} AND {pUntilDate}

Code in window:
MyQuery.pFromDate = FormControl1
MyQuery.pUntilDate = FormControl2
IF HExecuteQuery(MyQuery,hQueryDefault) THEN
...

Cheers,

Peter

von Peter Holemans - am 14.05.2013 08:52
Peter,

Thanks for confirming.

I was under the impression that such a query may not work in HF.

von Yogi Yang - am 14.05.2013 10:13
Are there any possibilities of create a (data) file in memory and then binding it to a table control in a window?

At time this is what I do.

If the data that I want cannot be fetched using one single query what I do is create a (data) file in memory and then populate this memory file with actual from multiple quries and then bind this memory file to a grid.

This is possible for me as I use SQLite for most of my development and SQLite support creating database and tables in memory.

von Yogi Yang - am 14.05.2013 14:28
Hello Yogi

Your query is a file in memory and can be treated exactly the same as any other HyperFile. You can add records to it and change the data in fields with assignments
MyQuery.fieldName = "Fred"
Recordmodify(Myquery)

However, it would be much simpler to just read through the query and write the records directly into the table as I mentioned in my earlier post. All you need is a foreign key value in the other queries to lookup the other pieces of information you require. Queries can access the original file indexes for searches.


//Query filled with invoice transactions
FOR ALL CRTransJOQry
LCredName = ""
//Query filled with active creditor records
//The index "CRCleunik" is the primary key index of the Creditor File and is a Foriegn key
//in the CRTransJoQry
//Because the CRLupQry query is built from records in the Creditor File, the file index
//can be used to search the CRLupQry query so I can retrieve the creditor name
IF HReadSeekFirst(CRLupQry,"CRCLEUNIK",CRTransJOQry.CRCLEUNIK)
LCredName = CRLupQry.CreditorName

....
TableAddLine(Mytable,CRTransJoQry.TransNo,LCredName)
End //FOR ALL CRTransJOQry



Regards
Al

von Al - am 14.05.2013 18:50
Hi YY,

Yes you can... Classes are the way to go in that sense. FileToSource() and SourceToFile() are your friend.

Have a look at my document: http://repository.windev.com/resource.awp?file_id=91;exemple-pour-utiliser-une-strategie-poo.

There is also a video available on WXLive.us.

Best regards,

Peter H.

von Peter Holemans - am 15.05.2013 08:03
Peter,

Thanks for the link.

I have already downloade this eBook of your. :)

But actually I felt that I am too young (as far as WD is concered) to study and digest your material as I have still not touched upon OO of WD.

But as I master WD I will surely study your eBook and make the most of it!

Regards,

Yogi Yang

von Yogi Yang - am 15.05.2013 12:08
Hello All,

If I use analysis then would it be possible to distribute my app without actual database with it?

I mean will the application that is developed with Analysis generate necessary data structure and base data automatically?

Here by base data I mean that there are a few master data like users.

TIA

Yogi Yang

von Yogi Yang - am 16.05.2013 07:40
Hello Yogi

The analysis option in the project definition has an auto file create if not found option, so you distribute the app with whatever base files you need and when it first runs, it will create all the missing ones as they are called by the app.

Regards
Al

von Al - am 16.05.2013 08:13
In short:
hCreationifnotfound(*) in the project init code (After setting the connection if a specific connection is used)

Cheers,

P.

von Peter Holemans - am 16.05.2013 09:03
Hello Yogi

The HcreationIfNotFound option in the project definition is faster than using it in the init because it only creates the files as the application calls for them. The HCreationIfNotFound("*") in the init causes the application to create every file required on the first run and on each subsequent startup of the app, it will check to see if it needs to create new files by testing if they exist which can slow down the opening of the app considerably.
If you want to use it instead of the option in the project definition, then also use the HDeleayedOpen option which then makes it operate the same as the option in the project definition

However I have no experience using it with a connection so maybe in that case you have to use the command in the init with the delay option.

Regards
Al

von Al - am 16.05.2013 10:00
Hi Al & Peter,

What about basic data that may be required for the software to operate properly.

Like say for example Users data, will that be added automatically also, so that any user can log on to it after running the software for the first time?

TIA

Yogi Yang

von Yogi Yang - am 16.05.2013 10:47
Hello Yogi

If you elect to use the builtin groupware you can send it out blank and it will create a Supervisor user. I prefer to make up some default users and groups with common options set already - e.g groups for Payroll, Accounts etc as this makes it easeir for users.
If you have any data files for descriptions or other lookups etc then include those files separately in your installation. If you make them part of the ecompiled exe they are set to read only.

Regards
Al

von Al - am 16.05.2013 14:47
In the software that I am going to start conversion it works off line meaning with local database and when the PC is connected to internet it will download and/or upload all the changes with a MySQL database sitting on a server.

Would such a feature be possible directly without coding will I have to code this?

Actually in the original software I have coded this sync part but I was wondering if WD will make it easy for me to achieve this with zero or minimum coding.

TIA

Yogi Yang

von Yogi Yang - am 17.05.2013 13:49
Hello Yogi


You may be better off starting a new thread for this type of question as sometimes people don't revisit old threads.
Can you prefix the topic with the version of Windev that you will be using and whether you will also be using Webdev or not as it will affect the answers.

Regards
Al

von Al - am 17.05.2013 14:32

Re: Remark on HcreationIfNotFound and hDelayedOpening

Hello to you all,

In my project there are a few dozen of files.
I use HFCS and the server is on an other adres. So it is a wan-connection.
Using HcreationIfNotFound for all the files uses 2.7 seconds.
Using it with the parameter hDelayedOpening should go faster (I thouhgt).
No... took in total 5.8 seconds. More than double the time.

Just my two cents.

von Frans - am 17.05.2013 14:38
Hello Frans

It would be interesting to see what the timing was if you used the project option to set the HcreationIfNotFound as I believe that it only creates files as the app calls for them so there should be no initial delay. All of my experience has been with local data, so there may be other factors coming in to play when the data is remote as your is.

Regards
Al

von Al - am 17.05.2013 17:01
Zur Information:
MySnip.de hat keinen Einfluss auf die Inhalte der Beiträge. Bitte kontaktieren Sie den Administrator des Forums bei Problemen oder Löschforderungen über die Kontaktseite.
Falls die Kontaktaufnahme mit dem Administrator des Forums fehlschlägt, kontaktieren Sie uns bitte über die in unserem Impressum angegebenen Daten.