<![CDATA[HMGforum.com]]> http://mail.hmgforum.com Smartfeed extension for phpBB <![CDATA[HMG News and Updates :: anonymous hookup site :: Reply by MigSoft]]> 2025-09-09T14:27:36+00:00 2025-09-09T14:27:36+00:00 http://mail.hmgforum.com/viewtopic.php?f=2&t=2430&p=71894#p71894 https://privateladyescorts.com


erotic dating without chat ]]>
https://privateladyescorts.com


erotic dating without chat ]]>
<![CDATA[HMG General Help :: Notepad++ update :: Author RPC]]> 2025-08-20T06:05:17+00:00 2025-08-20T06:05:17+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7686&p=71862#p71862 1) I have recently dowloaded latest version of Notepad++ for creating/editing my HMG code. I find following important features missing.
1. Auto-suggestion for codes is missing. Pls see enclosed SS where typing str ( shows arguments required and what the function does.
2. On clicking Function list icon I don't see any functions in right side window.
Can anyone suggest how to get these features in latest version of Notepad++.
If this is not possible. Pls suggest any other alternative code editor.
2) Does HMG provide any capability to convert PDF files to TEXT or CSV format maintaining original layout of PDF file.

Thanks
rpc

Attachments


HMG_copilot.png (387.93 KiB)

]]>
1) I have recently dowloaded latest version of Notepad++ for creating/editing my HMG code. I find following important features missing.
1. Auto-suggestion for codes is missing. Pls see enclosed SS where typing str ( shows arguments required and what the function does.
2. On clicking Function list icon I don't see any functions in right side window.
Can anyone suggest how to get these features in latest version of Notepad++.
If this is not possible. Pls suggest any other alternative code editor.
2) Does HMG provide any capability to convert PDF files to TEXT or CSV format maintaining original layout of PDF file.

Thanks
rpc

Attachments


HMG_copilot.png (387.93 KiB)

]]>
<![CDATA[HMG General Help :: Re: Notepad++ update :: Reply by serge_girard]]> 2025-08-20T13:25:51+00:00 2025-08-20T13:25:51+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7686&p=71863#p71863
I don't think there is nowhere such a application who can, besides Adobe Acrobat?
Convert PDF into readable text is a thing I sure would like to have... SumatraPDF maybe? Or this: https://pdftotext.com/]]>

I don't think there is nowhere such a application who can, besides Adobe Acrobat?
Convert PDF into readable text is a thing I sure would like to have... SumatraPDF maybe? Or this: https://pdftotext.com/]]>
<![CDATA[HMG General Help :: Re: Notepad++ update :: Reply by serge_girard]]> 2025-08-20T14:03:28+00:00 2025-08-20T14:03:28+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7686&p=71864#p71864 https://www.xpdfreader.com/download.html]]> https://www.xpdfreader.com/download.html]]> <![CDATA[HMG General Help :: Re: Notepad++ update :: Reply by RPC]]> 2025-08-20T17:45:47+00:00 2025-08-20T17:45:47+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7686&p=71865#p71865 I want to use pdf to text conversion in HMG code so your second link will be useful
rpc]]>
I want to use pdf to text conversion in HMG code so your second link will be useful
rpc]]>
<![CDATA[HMG General Help :: Re: Notepad++ update :: Reply by serge_girard]]> 2025-08-20T18:08:34+00:00 2025-08-20T18:08:34+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7686&p=71866#p71866 <![CDATA[HMG General Help :: Re: Notepad++ update :: Reply by RPC]]> 2025-08-21T14:30:09+00:00 2025-08-21T14:30:09+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7686&p=71868#p71868 viewtopic.php?t=6661 this link.
Thank you Tiger]]>
viewtopic.php?t=6661 this link.
Thank you Tiger]]>
<![CDATA[HMG General Help :: Talking to textbox :: Author franco]]> 2025-09-09T16:27:05+00:00 2025-09-09T16:27:05+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7698&p=71895#p71895 I would like to fill entry screens with my voice to save typing.
Thanks in advance.]]>
I would like to fill entry screens with my voice to save typing.
Thanks in advance.]]>
<![CDATA[HMG General Help :: Re: Talking to textbox :: Reply by franco]]> 2025-09-10T15:03:34+00:00 2025-09-10T15:03:34+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7698&p=71896#p71896 It is great for edit input or even item number or description of invoices, or customer information.
I takes a bit to get used to.]]>
It is great for edit input or even item number or description of invoices, or customer information.
I takes a bit to get used to.]]>
<![CDATA[HMG General Help :: Re: Talking to textbox :: Reply by serge_girard]]> 2025-09-11T06:46:57+00:00 2025-09-11T06:46:57+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7698&p=71900#p71900
Serge]]>

Serge]]>
<![CDATA[HMG General Help :: Re: Talking to textbox :: Reply by franco]]> 2025-09-11T15:44:25+00:00 2025-09-11T15:44:25+00:00 http://mail.hmgforum.com/viewtopic.php?f=5&t=7698&p=71901#p71901 Then whenever it opens it moves to the same spot on the screen. To used you press the mic button.
I haven`t created a button yet to open windows talk.
I am using windows11 . I think it should work with windows 10.
To try ,in program when in a entry screen or even windows notepad Press the Windows key plus H then just talk.
I am using it now to write my edit to you. It takes getting used to.
I don't know what command in HMG. I think action keypress Windows + H. I'm going to try later today.
Give it a try Serge. Let me know how it works for you.]]>
Then whenever it opens it moves to the same spot on the screen. To used you press the mic button.
I haven`t created a button yet to open windows talk.
I am using windows11 . I think it should work with windows 10.
To try ,in program when in a entry screen or even windows notepad Press the Windows key plus H then just talk.
I am using it now to write my edit to you. It takes getting used to.
I don't know what command in HMG. I think action keypress Windows + H. I'm going to try later today.
Give it a try Serge. Let me know how it works for you.]]>
<![CDATA[HMG Tutorials and Tips :: Re: NOTEPAD ++ 7.9.1 NEW STRUCTURE OF FUNCTION LIST :: Reply by RPC]]> 2025-08-21T14:28:22+00:00 2025-08-21T14:28:22+00:00 http://mail.hmgforum.com/viewtopic.php?f=6&t=6661&p=71867#p71867
Tiger wrote: Thu Nov 05, 2020 6:16 am Hi ALL,

The structure of function list has been changed on the version of notepad++ 7.91 …

You can refer to following path to make it work ...

HMG_userDefineLangs.XML ==> \Notepad++\userDefineLangs\

HMG_functionList.xml ==> \Notepad++\functionList\

overrideMap.xml ==> \Notepad++\functionList\

HMG.xmll ==>\Notepad++\autoCompletion\

You can refer to the attached file to do the modification ...
I found it very useful for ver 8.8.5
Thanks]]>
Tiger wrote: Thu Nov 05, 2020 6:16 am Hi ALL,

The structure of function list has been changed on the version of notepad++ 7.91 …

You can refer to following path to make it work ...

HMG_userDefineLangs.XML ==> \Notepad++\userDefineLangs\

HMG_functionList.xml ==> \Notepad++\functionList\

overrideMap.xml ==> \Notepad++\functionList\

HMG.xmll ==>\Notepad++\autoCompletion\

You can refer to the attached file to do the modification ...
I found it very useful for ver 8.8.5
Thanks]]>
<![CDATA[HMG Tutorials and Tips :: Re: NOTEPAD ++ 7.9.1 NEW STRUCTURE OF FUNCTION LIST :: Reply by tonton2]]> 2025-08-24T10:14:05+00:00 2025-08-24T10:14:05+00:00 http://mail.hmgforum.com/viewtopic.php?f=6&t=6661&p=71873#p71873
RPC wrote: Thu Aug 21, 2025 2:28 pm
Tiger wrote: Thu Nov 05, 2020 6:16 am Hi ALL,

The structure of function list has been changed on the version of notepad++ 7.91 …

You can refer to following path to make it work ...

HMG_userDefineLangs.XML ==> \Notepad++\userDefineLangs\

HMG_functionList.xml ==> \Notepad++\functionList\

overrideMap.xml ==> \Notepad++\functionList\

HMG.xmll ==>\Notepad++\autoCompletion\

You can refer to the attached file to do the modification ...
I found it very useful for ver 8.8.5
Thanks
bonjour
It gives me "import failed"]]>
RPC wrote: Thu Aug 21, 2025 2:28 pm
Tiger wrote: Thu Nov 05, 2020 6:16 am Hi ALL,

The structure of function list has been changed on the version of notepad++ 7.91 …

You can refer to following path to make it work ...

HMG_userDefineLangs.XML ==> \Notepad++\userDefineLangs\

HMG_functionList.xml ==> \Notepad++\functionList\

overrideMap.xml ==> \Notepad++\functionList\

HMG.xmll ==>\Notepad++\autoCompletion\

You can refer to the attached file to do the modification ...
I found it very useful for ver 8.8.5
Thanks
bonjour
It gives me "import failed"]]>
<![CDATA[Harbour, MingW updates & releases :: Re: GCC 15.2 was released on August 8, 2025 :: Reply by srvet_claudio]]> 2025-08-18T22:54:12+00:00 2025-08-18T22:54:12+00:00 http://mail.hmgforum.com/viewtopic.php?f=7&t=7685&p=71860#p71860 <![CDATA[Harbour, MingW updates & releases :: Re: GCC 15.2 was released on August 8, 2025 :: Reply by gfilatov]]> 2025-08-22T14:17:15+00:00 2025-08-22T14:17:15+00:00 http://mail.hmgforum.com/viewtopic.php?f=7&t=7685&p=71869#p71869
There is a good news. :D

I have successfully tested MinGW 15.2 (64-bit) with the latest version of the Harbour compiler (August, 22).

You can see the result in the picture below. :arrow:

Image

Thank you for your attention.]]>

There is a good news. :D

I have successfully tested MinGW 15.2 (64-bit) with the latest version of the Harbour compiler (August, 22).

You can see the result in the picture below. :arrow:

Image

Thank you for your attention.]]>
<![CDATA[Harbour, MingW updates & releases :: Re: GCC 15.2 was released on August 8, 2025 :: Reply by serge_girard]]> 2025-08-22T14:35:00+00:00 2025-08-22T14:35:00+00:00 http://mail.hmgforum.com/viewtopic.php?f=7&t=7685&p=71870#p71870 <![CDATA[General :: Re: GRID - HEADER / CABECERA :: Reply by serge_girard]]> 2025-08-17T11:49:07+00:00 2025-08-17T11:49:07+00:00 http://mail.hmgforum.com/viewtopic.php?f=24&t=7350&p=71858#p71858 Serge]]> Serge]]> <![CDATA[General :: Re: GRID - HEADER / CABECERA :: Reply by tonton2]]> 2025-08-17T13:53:13+00:00 2025-08-17T13:53:13+00:00 http://mail.hmgforum.com/viewtopic.php?f=24&t=7350&p=71859#p71859 (dans ce programme , lorsque je fais le produit aLigne[6] :=aLigne[3]*aLigne[4], dans le Grid_Temp la cellule reste toujours à 0 , alors que mzginfo(aLigne[6] me donne le produit exact , comment faire pour que laigne[6]:=aLigne[3]*aLigne[4], soit affiché dans la cellule appropriée)
traduction en anglais dans " grid_temp"
Dans ce programme, lorsque j'effectue le calcul aLigne[6] := aLigne[3] * aLigne[4], la cellule dans Grid_Temp reste 0, même si MsgInfo(aLigne[6]) donne le bon produit. Comment puis-je m'assurer que aLigne[6] := aLigne[3] * aLigne[4] est affiché dans la cellule appropriée. in Grid_temp

Attachments

Grille_Grid (1).rar (1369.64 KiB)
]]>
(dans ce programme , lorsque je fais le produit aLigne[6] :=aLigne[3]*aLigne[4], dans le Grid_Temp la cellule reste toujours à 0 , alors que mzginfo(aLigne[6] me donne le produit exact , comment faire pour que laigne[6]:=aLigne[3]*aLigne[4], soit affiché dans la cellule appropriée)
traduction en anglais dans " grid_temp"
Dans ce programme, lorsque j'effectue le calcul aLigne[6] := aLigne[3] * aLigne[4], la cellule dans Grid_Temp reste 0, même si MsgInfo(aLigne[6]) donne le bon produit. Comment puis-je m'assurer que aLigne[6] := aLigne[3] * aLigne[4] est affiché dans la cellule appropriée. in Grid_temp

Attachments

Grille_Grid (1).rar (1369.64 KiB)
]]>
<![CDATA[General :: Re: libmariadb.dll :: Reply by Ismach]]> 2025-08-19T19:25:15+00:00 2025-08-19T19:25:15+00:00 http://mail.hmgforum.com/viewtopic.php?f=24&t=7681&p=71861#p71861 <![CDATA[General :: xBase Package :: Author msdn]]> 2025-09-02T16:30:23+00:00 2025-09-02T16:30:23+00:00 http://mail.hmgforum.com/viewtopic.php?f=24&t=7693&p=71885#p71885 Visit the website and see how to purchase.

https://harbourdeveloper.blogspot.com/

Thank you very much for your attention.]]>
Visit the website and see how to purchase.

https://harbourdeveloper.blogspot.com/

Thank you very much for your attention.]]>
<![CDATA[HMG Source :: Grid error while editing data :: Author mol]]> 2025-09-08T15:36:49+00:00 2025-09-08T15:36:49+00:00 http://mail.hmgforum.com/viewtopic.php?f=8&t=7695&p=71888#p71888 I declrare 6 columns, key Alt+A can be used to add empty row. Then, clicking in first column you can edit 5 columns, but next ENTER key doesn't move focus to column 6.
When I click by the mouse on the column 6, I can ener value, but it causes an error in VALID block which saves data to an array.

Can somebody try to compile my sample?

Code: Select all

#include "hmg.ch"

#define COL_RECNO	7

FUNCTION Main()

	public aStru 
	PUBLIC aData := {}

	private abValid := array(6)
	private bValid := {|| UpdateData()}
	
	
	SET LANGUAGE TO POLISH 
	HB_LANGSELECT('PL')
	HB_SETCODEPAGE("PL852") 
	SET DELETED ON
	SET CENTURY ON
	SET DATE TO GERMAN

	// tablica bloków walidacyjnych
	
	aFill(abValid, bValid)
	
	aStru := {;
		{ "NAZWA",     "C", 30, 0 },;
		{ "UZYTKOWNIK","C", 30, 0 },;
		{ "HASLO",     "C", 30, 0 },;
		{ "SCIEZKA",   "C", 80, 0 },;
		{ "FIRMA",     "C", 50, 0 },;
		{ "Link_d",    "C",254, 0 } }

	scr := ""
	if .not.file(scr+"linki.dbf")
		
		DBCREATE( scr+"LINKI.DBF", aStru )
	endif

   USE (scr+"LINKI.DBF") SHARED alias linki
   GO TOP


	// Insert data to an array
	aData:={}
	i=0
	DO WHILE !EOF()
		AADD(aData, { linki->nazwa, linki->uzytkownik, linki->haslo, linki->sciezka,linki->firma,linki->link_d, linki->(recNo()) })
		SKIP
		i+=1
	ENDDO
	
   DEFINE WINDOW Form_1 ;
      AT 0,0 ;
      WIDTH 1500 HEIGHT 800 MAIN ;
      TITLE 'Link view/edit - Alt+A adds empty row to grid, try to edit it'

	@ 10,10 GRID Grid_1 ;
		WIDTH 1400 ;
		HEIGHT 700 ;
		HEADERS { "NAZWA", "UZYTKOWNIK", "HASLO", "SCIEZKA", "FIRMA","Link długi" } ;		
		WIDTHS { 200, 200, 200, 300, 200 ,400} ;
		ITEMS NIL ;
		EDIT ;
		VIRTUAL ;
		ON QUERYDATA Grid_1_OnQueryData();
		JUSTIFY { GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT};
		COLUMNVALID abValid


	@ 720, 10 BUTTON BT_Save ;
		CAPTION 'Zapisz zmiany' ;
		WIDTH 120 HEIGHT 28 ;
		ACTION SaveDBF()

   END WINDOW

	ON KEY ALT+Q OF FORM_1 ACTION FORM_1.RELEASE
	ON KEY ALT+A OF FORM_1 ACTION AddEmptyRowtoArray()
	Form_1.Grid_1.ItemCount := len(aData)
	Form_1.CENTER
   Form_1.ACTIVATE

RETURN NIL
*----------------------
function Grid_1_OnQueryData
	local nRow, nCol
	
	nRow := This.QueryRowIndex
	nCol := This.QueryColIndex
	
	if nRow>0 .and. nCol >0
		This.QueryData := aData[nRow, nCol]
	endif

return
*----------------------
function AddEmptyRowtoArray
	local i
	local aEmptyRow := {}
	
	for i:=1 to len(aStru)
		if aStru[i, 2] == "C"
			aAdd(aEmptyRow, "")
		elseif aStru[i, 2] == "N"
			aAdd(aEmptyRow, 0)
		elseif aStru[i, 2] == "L"
			aAdd(aEmptyRow, .f.)
		elseif aStru[i, 2] == "D"
			aAdd(aEmptyRow, 0d0)
		endif 
	next i
	// and one another clumn for #recno
	aAdd(aEmptyRow, 0)
	aAdd(aData, aEmptyRow)
	Form_1.Grid_1.ItemCount := len(aData)
	Form_1.Grid_1.Value := { len(aData), 1 }
return
*----------------------
FUNCTION UpdateData
	
	local nRow, nCol, xValue
	
	nRow := this.CellRowIndex
	nCol := this.CellColIndex
	xValue := this.CellValue
	
	MsGDebug("Writing to aData[" + hb_ntos(nRow) + ","+ hb_ntos(nCol)+"]", xValue)
	aData[nRow, nCol] := xValue
	
RETURN .t.
*----------------------
FUNCTION SaveDBF
	MsgStop("function in progress...")
RETURN
Error below:

Code: Select all

Date:08.09.2025 Time: 17:31:26
Error BASE/1132 Błąd zakresu tablicy: Nieprawidłowa liczba argumentów
Called from UPDATEDATA(128) 
Called from (b)MAIN(11) 
Called from _DOCONTROLEVENTPROCEDURE(6033) 
Called from _HMG_GRIDINPLACEEDITOK(1513) 
Called from (b)_HMG_GRIDINPLACEEDIT(1066) 
Called from _DOCONTROLEVENTPROCEDURE(6033) 
Called from EVENTS(821) 
Called from DOMESSAGELOOP(0) 
Called from _ACTIVATEWINDOW(5694) 
Called from _HMG_GRIDINPLACEEDIT(1299) 
Called from _HMG_GRIDINPLACEKBDEDIT(1753) 
Called from EVENTS(2213) 
Called from DOMESSAGELOOP(0) 
Called from _ACTIVATEWINDOW(5694) 
Called from DOMETHOD(9080) 
Called from MAIN(81) 
]]>
I declrare 6 columns, key Alt+A can be used to add empty row. Then, clicking in first column you can edit 5 columns, but next ENTER key doesn't move focus to column 6.
When I click by the mouse on the column 6, I can ener value, but it causes an error in VALID block which saves data to an array.

Can somebody try to compile my sample?

Code: Select all

#include "hmg.ch"

#define COL_RECNO	7

FUNCTION Main()

	public aStru 
	PUBLIC aData := {}

	private abValid := array(6)
	private bValid := {|| UpdateData()}
	
	
	SET LANGUAGE TO POLISH 
	HB_LANGSELECT('PL')
	HB_SETCODEPAGE("PL852") 
	SET DELETED ON
	SET CENTURY ON
	SET DATE TO GERMAN

	// tablica bloków walidacyjnych
	
	aFill(abValid, bValid)
	
	aStru := {;
		{ "NAZWA",     "C", 30, 0 },;
		{ "UZYTKOWNIK","C", 30, 0 },;
		{ "HASLO",     "C", 30, 0 },;
		{ "SCIEZKA",   "C", 80, 0 },;
		{ "FIRMA",     "C", 50, 0 },;
		{ "Link_d",    "C",254, 0 } }

	scr := ""
	if .not.file(scr+"linki.dbf")
		
		DBCREATE( scr+"LINKI.DBF", aStru )
	endif

   USE (scr+"LINKI.DBF") SHARED alias linki
   GO TOP


	// Insert data to an array
	aData:={}
	i=0
	DO WHILE !EOF()
		AADD(aData, { linki->nazwa, linki->uzytkownik, linki->haslo, linki->sciezka,linki->firma,linki->link_d, linki->(recNo()) })
		SKIP
		i+=1
	ENDDO
	
   DEFINE WINDOW Form_1 ;
      AT 0,0 ;
      WIDTH 1500 HEIGHT 800 MAIN ;
      TITLE 'Link view/edit - Alt+A adds empty row to grid, try to edit it'

	@ 10,10 GRID Grid_1 ;
		WIDTH 1400 ;
		HEIGHT 700 ;
		HEADERS { "NAZWA", "UZYTKOWNIK", "HASLO", "SCIEZKA", "FIRMA","Link długi" } ;		
		WIDTHS { 200, 200, 200, 300, 200 ,400} ;
		ITEMS NIL ;
		EDIT ;
		VIRTUAL ;
		ON QUERYDATA Grid_1_OnQueryData();
		JUSTIFY { GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT};
		COLUMNVALID abValid


	@ 720, 10 BUTTON BT_Save ;
		CAPTION 'Zapisz zmiany' ;
		WIDTH 120 HEIGHT 28 ;
		ACTION SaveDBF()

   END WINDOW

	ON KEY ALT+Q OF FORM_1 ACTION FORM_1.RELEASE
	ON KEY ALT+A OF FORM_1 ACTION AddEmptyRowtoArray()
	Form_1.Grid_1.ItemCount := len(aData)
	Form_1.CENTER
   Form_1.ACTIVATE

RETURN NIL
*----------------------
function Grid_1_OnQueryData
	local nRow, nCol
	
	nRow := This.QueryRowIndex
	nCol := This.QueryColIndex
	
	if nRow>0 .and. nCol >0
		This.QueryData := aData[nRow, nCol]
	endif

return
*----------------------
function AddEmptyRowtoArray
	local i
	local aEmptyRow := {}
	
	for i:=1 to len(aStru)
		if aStru[i, 2] == "C"
			aAdd(aEmptyRow, "")
		elseif aStru[i, 2] == "N"
			aAdd(aEmptyRow, 0)
		elseif aStru[i, 2] == "L"
			aAdd(aEmptyRow, .f.)
		elseif aStru[i, 2] == "D"
			aAdd(aEmptyRow, 0d0)
		endif 
	next i
	// and one another clumn for #recno
	aAdd(aEmptyRow, 0)
	aAdd(aData, aEmptyRow)
	Form_1.Grid_1.ItemCount := len(aData)
	Form_1.Grid_1.Value := { len(aData), 1 }
return
*----------------------
FUNCTION UpdateData
	
	local nRow, nCol, xValue
	
	nRow := this.CellRowIndex
	nCol := this.CellColIndex
	xValue := this.CellValue
	
	MsGDebug("Writing to aData[" + hb_ntos(nRow) + ","+ hb_ntos(nCol)+"]", xValue)
	aData[nRow, nCol] := xValue
	
RETURN .t.
*----------------------
FUNCTION SaveDBF
	MsgStop("function in progress...")
RETURN
Error below:

Code: Select all

Date:08.09.2025 Time: 17:31:26
Error BASE/1132 Błąd zakresu tablicy: Nieprawidłowa liczba argumentów
Called from UPDATEDATA(128) 
Called from (b)MAIN(11) 
Called from _DOCONTROLEVENTPROCEDURE(6033) 
Called from _HMG_GRIDINPLACEEDITOK(1513) 
Called from (b)_HMG_GRIDINPLACEEDIT(1066) 
Called from _DOCONTROLEVENTPROCEDURE(6033) 
Called from EVENTS(821) 
Called from DOMESSAGELOOP(0) 
Called from _ACTIVATEWINDOW(5694) 
Called from _HMG_GRIDINPLACEEDIT(1299) 
Called from _HMG_GRIDINPLACEKBDEDIT(1753) 
Called from EVENTS(2213) 
Called from DOMESSAGELOOP(0) 
Called from _ACTIVATEWINDOW(5694) 
Called from DOMETHOD(9080) 
Called from MAIN(81) 
]]>
<![CDATA[HMG Source :: Re: Grid error while editing data :: Reply by nekbmm]]> 2025-09-09T09:37:18+00:00 2025-09-09T09:37:18+00:00 http://mail.hmgforum.com/viewtopic.php?f=8&t=7695&p=71891#p71891
mol wrote: Mon Sep 08, 2025 3:36 pm I have a strange error while editing data in Virtual Grid.
I declrare 6 columns, key Alt+A can be used to add empty row. Then, clicking in first column you can edit 5 columns, but next ENTER key doesn't move focus to column 6.
When I click by the mouse on the column 6, I can ener value, but it causes an error in VALID block which saves data to an array.

Can somebody try to compile my sample?

It's the same for me!
I'm using hmg 3.44.

Pozdrav NEX.]]>
mol wrote: Mon Sep 08, 2025 3:36 pm I have a strange error while editing data in Virtual Grid.
I declrare 6 columns, key Alt+A can be used to add empty row. Then, clicking in first column you can edit 5 columns, but next ENTER key doesn't move focus to column 6.
When I click by the mouse on the column 6, I can ener value, but it causes an error in VALID block which saves data to an array.

Can somebody try to compile my sample?

It's the same for me!
I'm using hmg 3.44.

Pozdrav NEX.]]>
<![CDATA[HMG Source :: Re: Grid error while editing data :: Reply by gfilatov]]> 2025-09-09T12:22:57+00:00 2025-09-09T12:22:57+00:00 http://mail.hmgforum.com/viewtopic.php?f=8&t=7695&p=71892#p71892
I confirm also this issue.

There is a workaround for the problem: your last column should have a lenght to show this column on screen entirely at initializing your grid.

Please review the updated working code below.

Code: Select all

#include "hmg.ch"

#define COL_RECNO	7

FUNCTION Main()

	public aStru 
	PUBLIC aData := {}

	private abValid := array(6)
	private bValid := {|| UpdateData()}
	
	
	SET LANGUAGE TO POLISH 
	HB_LANGSELECT('PL')
	HB_SETCODEPAGE("PL852") 
	SET DELETED ON
	SET CENTURY ON
	SET DATE TO GERMAN

	// tablica bloków walidacyjnych
	
	aFill(abValid, bValid)
	
	aStru := {;
		{ "NAZWA",     "C", 30, 0 },;
		{ "UZYTKOWNIK","C", 30, 0 },;
		{ "HASLO",     "C", 30, 0 },;
		{ "SCIEZKA",   "C", 80, 0 },;
		{ "FIRMA",     "C", 50, 0 },;
		{ "Link_d",    "C",254, 0 } }

	scr := ""
	if .not.file(scr+"linki.dbf")
		
		DBCREATE( scr+"LINKI.DBF", aStru )
	endif

   USE (scr+"LINKI.DBF") SHARED alias linki
   GO TOP


	// Insert data to an array
	aData:={}
	i=0
	DO WHILE !EOF()
		AADD(aData, { linki->nazwa, linki->uzytkownik, linki->haslo, linki->sciezka,linki->firma,linki->link_d, linki->(recNo()) })
		SKIP
		i+=1
	ENDDO
	
   DEFINE WINDOW Form_1 ;
      AT 0,0 ;
      WIDTH 1400 HEIGHT 800 MAIN ;
      TITLE 'Link view/edit - Alt+A adds empty row to grid, try to edit it'

	@ 10,10 GRID Grid_1 ;
		WIDTH 1350 ;
		HEIGHT 700 ;
		HEADERS { "NAZWA", "UZYTKOWNIK", "HASLO", "SCIEZKA", "FIRMA","Link długi" } ;		
		WIDTHS { 200, 200, 200, 300, 200 ,400} ;
		ITEMS NIL ;
		EDIT ;
		CELLNAVIGATION ;
		VIRTUAL ;
		ON QUERYDATA Grid_1_OnQueryData();
		JUSTIFY { GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT};
		COLUMNVALID abValid


	@ 720, 10 BUTTON BT_Save ;
		CAPTION 'Zapisz zmiany' ;
		WIDTH 120 HEIGHT 28 ;
		ACTION SaveDBF()

   END WINDOW

	ON KEY ALT+Q OF FORM_1 ACTION FORM_1.RELEASE
	ON KEY ALT+A OF FORM_1 ACTION AddEmptyRowtoArray()
	Form_1.Grid_1.ItemCount := len(aData)
	Form_1.Grid_1.ColumnWidth(6) := 230
	Form_1.CENTER
   Form_1.ACTIVATE

RETURN NIL
*----------------------
function Grid_1_OnQueryData
	local nRow, nCol
	
	nRow := This.QueryRowIndex
	nCol := This.QueryColIndex
	
	if nRow>0 .and. nCol >0
		This.QueryData := aData[nRow, nCol]
	endif

return
*----------------------
function AddEmptyRowtoArray
	local i
	local aEmptyRow := {}
	
	for i:=1 to len(aStru)
		if aStru[i, 2] == "C"
			aAdd(aEmptyRow, "")
		elseif aStru[i, 2] == "N"
			aAdd(aEmptyRow, 0)
		elseif aStru[i, 2] == "L"
			aAdd(aEmptyRow, .f.)
		elseif aStru[i, 2] == "D"
			aAdd(aEmptyRow, 0d0)
		endif 
	next i
	// and one another clumn for #recno
	aAdd(aEmptyRow, 0)
	aAdd(aData, aEmptyRow)
	Form_1.Grid_1.ItemCount := len(aData)
	Form_1.Grid_1.Value := { len(aData), 1 }
return
*----------------------
FUNCTION UpdateData
	
	local nRow, nCol, xValue
	
	nRow := this.CellRowIndex
	nCol := this.CellColIndex
	xValue := this.CellValue
	
	MsgDebug("Writing to aData[" + hb_ntos(nRow) + ","+ hb_ntos(nCol)+"]", xValue)
	aData[nRow, nCol] := xValue
	
RETURN .t.
*----------------------
FUNCTION SaveDBF
	MsgStop("function in progress...")
RETURN
]]>

I confirm also this issue.

There is a workaround for the problem: your last column should have a lenght to show this column on screen entirely at initializing your grid.

Please review the updated working code below.

Code: Select all

#include "hmg.ch"

#define COL_RECNO	7

FUNCTION Main()

	public aStru 
	PUBLIC aData := {}

	private abValid := array(6)
	private bValid := {|| UpdateData()}
	
	
	SET LANGUAGE TO POLISH 
	HB_LANGSELECT('PL')
	HB_SETCODEPAGE("PL852") 
	SET DELETED ON
	SET CENTURY ON
	SET DATE TO GERMAN

	// tablica bloków walidacyjnych
	
	aFill(abValid, bValid)
	
	aStru := {;
		{ "NAZWA",     "C", 30, 0 },;
		{ "UZYTKOWNIK","C", 30, 0 },;
		{ "HASLO",     "C", 30, 0 },;
		{ "SCIEZKA",   "C", 80, 0 },;
		{ "FIRMA",     "C", 50, 0 },;
		{ "Link_d",    "C",254, 0 } }

	scr := ""
	if .not.file(scr+"linki.dbf")
		
		DBCREATE( scr+"LINKI.DBF", aStru )
	endif

   USE (scr+"LINKI.DBF") SHARED alias linki
   GO TOP


	// Insert data to an array
	aData:={}
	i=0
	DO WHILE !EOF()
		AADD(aData, { linki->nazwa, linki->uzytkownik, linki->haslo, linki->sciezka,linki->firma,linki->link_d, linki->(recNo()) })
		SKIP
		i+=1
	ENDDO
	
   DEFINE WINDOW Form_1 ;
      AT 0,0 ;
      WIDTH 1400 HEIGHT 800 MAIN ;
      TITLE 'Link view/edit - Alt+A adds empty row to grid, try to edit it'

	@ 10,10 GRID Grid_1 ;
		WIDTH 1350 ;
		HEIGHT 700 ;
		HEADERS { "NAZWA", "UZYTKOWNIK", "HASLO", "SCIEZKA", "FIRMA","Link długi" } ;		
		WIDTHS { 200, 200, 200, 300, 200 ,400} ;
		ITEMS NIL ;
		EDIT ;
		CELLNAVIGATION ;
		VIRTUAL ;
		ON QUERYDATA Grid_1_OnQueryData();
		JUSTIFY { GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT};
		COLUMNVALID abValid


	@ 720, 10 BUTTON BT_Save ;
		CAPTION 'Zapisz zmiany' ;
		WIDTH 120 HEIGHT 28 ;
		ACTION SaveDBF()

   END WINDOW

	ON KEY ALT+Q OF FORM_1 ACTION FORM_1.RELEASE
	ON KEY ALT+A OF FORM_1 ACTION AddEmptyRowtoArray()
	Form_1.Grid_1.ItemCount := len(aData)
	Form_1.Grid_1.ColumnWidth(6) := 230
	Form_1.CENTER
   Form_1.ACTIVATE

RETURN NIL
*----------------------
function Grid_1_OnQueryData
	local nRow, nCol
	
	nRow := This.QueryRowIndex
	nCol := This.QueryColIndex
	
	if nRow>0 .and. nCol >0
		This.QueryData := aData[nRow, nCol]
	endif

return
*----------------------
function AddEmptyRowtoArray
	local i
	local aEmptyRow := {}
	
	for i:=1 to len(aStru)
		if aStru[i, 2] == "C"
			aAdd(aEmptyRow, "")
		elseif aStru[i, 2] == "N"
			aAdd(aEmptyRow, 0)
		elseif aStru[i, 2] == "L"
			aAdd(aEmptyRow, .f.)
		elseif aStru[i, 2] == "D"
			aAdd(aEmptyRow, 0d0)
		endif 
	next i
	// and one another clumn for #recno
	aAdd(aEmptyRow, 0)
	aAdd(aData, aEmptyRow)
	Form_1.Grid_1.ItemCount := len(aData)
	Form_1.Grid_1.Value := { len(aData), 1 }
return
*----------------------
FUNCTION UpdateData
	
	local nRow, nCol, xValue
	
	nRow := this.CellRowIndex
	nCol := this.CellColIndex
	xValue := this.CellValue
	
	MsgDebug("Writing to aData[" + hb_ntos(nRow) + ","+ hb_ntos(nCol)+"]", xValue)
	aData[nRow, nCol] := xValue
	
RETURN .t.
*----------------------
FUNCTION SaveDBF
	MsgStop("function in progress...")
RETURN
]]>
<![CDATA[HMG Source :: Re: Grid error while editing data :: Reply by mol]]> 2025-09-09T14:06:12+00:00 2025-09-09T14:06:12+00:00 http://mail.hmgforum.com/viewtopic.php?f=8&t=7695&p=71893#p71893 Thank you Grigorij for your solution!]]> Thank you Grigorij for your solution!]]> <![CDATA[HMG Samples :: EASY.SQL.2025.08.23 :: Author Roberto Lopez]]> 2025-08-23T16:33:33+00:00 2025-08-23T16:33:33+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7687&p=71871#p71871
Changes on this Version (2025.08.23):

- New: Methods for transaction support: StartTransaction(), Commit() and RollBack().

- New: Use(cDatabase) method. It selects the default database. Useful when connecting without
specifying a database or when working with multiple databases.

- Modified: Demo. Database and needed tables can be created from demo now. Various changes to show new library features.


This class must be considered EXPERIMENTAL.

My idea to start this library, was to have a wrapper for 'Simple SQL Interface' contribution by Mindaugas Kavaliauskas that I've used for many years.

This wrapper aims to have the following features:

- Handle all possible runtime error situations (bad parameters, connection, SQL syntax, etc.).

- Show all required progress information and error messages to the user.

- Handle simultaneous connections in an easy/intuitive way.


This is a very very basic documentation:


METHODS:


New(): Object Initialization
Returns: SELF (refers to the instance of the class that is being constructed).

Connect(cServer, cUser, cPassword [, cDatabase]): Connect to a MySql server.
Returns: .T. if connection was successful (.F. otherwise).

Select(cSelect,cWorkArea): cSelect must be a MySql SELECT statement.
A recordset is created with the name specified as cWorkArea.
Returns: .T. if query was successful (.F. otherwise).

Exec(cCommand): Executes a MySql command.
Returns: .T. if command was successfully executed (.F. otherwise).

Disconnect(): Disconnect from server.
Returns: NIL

CloseAreas(): Close all workareas open with 'Select' method (if any).
Returns: Number of workareas closed.

Insert(cTable, aCols): Insert row. aCols, specifies cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

Delete( cTable, cWhere ): Delete rows based on 'cWhere' condition.
Returns: .T. if command was successfully executed (.F. otherwise).

Update(cTable,cWhere,aCols): Modify rows based on 'cWhere' condition. aCols, specifies
cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

AffectedRows(): Returns the number of rows modified by the last executed
INSERT, UPDATE, or DELETE command.

Destroy(): Set all object variables to NIL, closes all workareas used by
'Select' method (if any) and disconnects.
Returns: NIL

StartTransaction(): Executes 'START TRANSACTION' command.

Commit(): Executes 'COMMIT' command.

RollBack(): Executes 'ROLLBACK' command.

Use(cDatabase): Selects the default database. Useful when connecting without
specifying a database or when working with multiple databases.



VARIABLES:


lError (Read Only): .T. if an error occurred on last operation (.F. otherwise).

cErrorDesc (Read Only): Error description (Empty if no error).

lShowMsgs: Determines if error/progress messages will be shown.

lTrace: When set to .T., a file called 'trace.log' containing last command
executed.

cNoQuoteChar: Set leftmost character indicator to instruct Update and Insert
methods to not quote a character value on aColumns
(cColumnName,xColumnValue) array (default value is '@').



MariaDB:


Last years, for new projects (even local-data ones), I've used portable MariaDB.

It is compact, fast, reliable, secure and requires no installation.

You can download it at https://mariadb.org/download/ and select 'ZIP file' on
'Package Type'. You can unpack it at any place (<base_folder>).

For newer versions, prior to start MariaDB, you must initialize data directory:

<base_folder>\bin\mysql_install_db.exe --datadir=<base_folder>\data

Then you can run MariaDB:

<base_folder>\bin\mysqld.exe

The default user is root with no password.

Best database utility: HeidiSQL (https://www.heidisql.com/)


I hope this be useful for someone.


Roberto.

Attachments

hmg.easy.sql.2025.08.23.zip (1789.19 KiB)
]]>

Changes on this Version (2025.08.23):

- New: Methods for transaction support: StartTransaction(), Commit() and RollBack().

- New: Use(cDatabase) method. It selects the default database. Useful when connecting without
specifying a database or when working with multiple databases.

- Modified: Demo. Database and needed tables can be created from demo now. Various changes to show new library features.


This class must be considered EXPERIMENTAL.

My idea to start this library, was to have a wrapper for 'Simple SQL Interface' contribution by Mindaugas Kavaliauskas that I've used for many years.

This wrapper aims to have the following features:

- Handle all possible runtime error situations (bad parameters, connection, SQL syntax, etc.).

- Show all required progress information and error messages to the user.

- Handle simultaneous connections in an easy/intuitive way.


This is a very very basic documentation:


METHODS:


New(): Object Initialization
Returns: SELF (refers to the instance of the class that is being constructed).

Connect(cServer, cUser, cPassword [, cDatabase]): Connect to a MySql server.
Returns: .T. if connection was successful (.F. otherwise).

Select(cSelect,cWorkArea): cSelect must be a MySql SELECT statement.
A recordset is created with the name specified as cWorkArea.
Returns: .T. if query was successful (.F. otherwise).

Exec(cCommand): Executes a MySql command.
Returns: .T. if command was successfully executed (.F. otherwise).

Disconnect(): Disconnect from server.
Returns: NIL

CloseAreas(): Close all workareas open with 'Select' method (if any).
Returns: Number of workareas closed.

Insert(cTable, aCols): Insert row. aCols, specifies cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

Delete( cTable, cWhere ): Delete rows based on 'cWhere' condition.
Returns: .T. if command was successfully executed (.F. otherwise).

Update(cTable,cWhere,aCols): Modify rows based on 'cWhere' condition. aCols, specifies
cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

AffectedRows(): Returns the number of rows modified by the last executed
INSERT, UPDATE, or DELETE command.

Destroy(): Set all object variables to NIL, closes all workareas used by
'Select' method (if any) and disconnects.
Returns: NIL

StartTransaction(): Executes 'START TRANSACTION' command.

Commit(): Executes 'COMMIT' command.

RollBack(): Executes 'ROLLBACK' command.

Use(cDatabase): Selects the default database. Useful when connecting without
specifying a database or when working with multiple databases.



VARIABLES:


lError (Read Only): .T. if an error occurred on last operation (.F. otherwise).

cErrorDesc (Read Only): Error description (Empty if no error).

lShowMsgs: Determines if error/progress messages will be shown.

lTrace: When set to .T., a file called 'trace.log' containing last command
executed.

cNoQuoteChar: Set leftmost character indicator to instruct Update and Insert
methods to not quote a character value on aColumns
(cColumnName,xColumnValue) array (default value is '@').



MariaDB:


Last years, for new projects (even local-data ones), I've used portable MariaDB.

It is compact, fast, reliable, secure and requires no installation.

You can download it at https://mariadb.org/download/ and select 'ZIP file' on
'Package Type'. You can unpack it at any place (<base_folder>).

For newer versions, prior to start MariaDB, you must initialize data directory:

<base_folder>\bin\mysql_install_db.exe --datadir=<base_folder>\data

Then you can run MariaDB:

<base_folder>\bin\mysqld.exe

The default user is root with no password.

Best database utility: HeidiSQL (https://www.heidisql.com/)


I hope this be useful for someone.


Roberto.

Attachments

hmg.easy.sql.2025.08.23.zip (1789.19 KiB)
]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.08.23 :: Reply by tonton2]]> 2025-08-24T08:56:00+00:00 2025-08-24T08:56:00+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7687&p=71872#p71872 <![CDATA[HMG Samples :: Re: EASY.SQL.2025.08.23 :: Reply by Roberto Lopez]]> 2025-08-26T13:22:14+00:00 2025-08-26T13:22:14+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7687&p=71877#p71877
tonton2 wrote: Sun Aug 24, 2025 8:56 am Merci beaucoup ; je vais l'etudier car j'utilise DBF et je voudrais m'initier au aux bases SQL
I hope that this library can be useful for you.]]>
tonton2 wrote: Sun Aug 24, 2025 8:56 am Merci beaucoup ; je vais l'etudier car j'utilise DBF et je voudrais m'initier au aux bases SQL
I hope that this library can be useful for you.]]>
<![CDATA[HMG Samples :: EASY.SQL.2025.08.26 :: Author Roberto Lopez]]> 2025-08-26T01:21:31+00:00 2025-08-26T01:21:31+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7688&p=71874#p71874
Changes on this Version (2025.08.26):

- New: SetLang(cLangId) method. Set library information messages language.
Useful when you do not want to use default language for messages
(current hb_langselect() setting).

Accepted values for <cLangId> are the following:

'EN' -> English
'ES' -> Spanish
'PT' -> Portuguese
'FR' -> French
'DE' -> German
'IT' -> Italian
'NL' -> Dutch
'SV' -> Swedish
'DA' -> Danish
'FI' -> Finnish
'NO' -> Norwegian
'HU' -> Hungarian

- New: 'lAutoReconnect' variable. When set to .T. (the default) operations that
requires connection to the server, on error, will check if the connection is still alive,
if not, reconnection will be attempted.

One BIG problem when working with some shared AMP hostings, are unexpected
disconnections. So, you could get frequent (and very frustrating)
'MySQL server has gone away' error messages.

To address this, I've added support for automatic handling of reconnections
to the library, so (hopefully) you should not care about this annoyance :D

- New: IsConnected() method. Returns .T. if the current connection still alive,
.F. if not.

- New: Reconnect() method. Attempts to re-connect using the current parameters.


This class must be considered EXPERIMENTAL.

My idea to start this library, was to have a wrapper for 'Simple SQL Interface' contribution by Mindaugas Kavaliauskas that I've used for many years.

This wrapper aims to have the following features:

- Handle all possible runtime error situations (bad parameters, connection, SQL syntax, etc.).

- Show all required progress information and error messages to the user.

- Handle simultaneous connections in an easy/intuitive way.

This is a very very basic documentation:

METHODS:

AffectedRows(): Returns the number of rows modified by the last executed
INSERT, UPDATE, or DELETE command.

CloseAreas(): Close all workareas open with 'Select' method (if any).
Returns: Number of workareas closed.

Commit(): Executes 'COMMIT' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Connect(cServer, cUser, cPassword [, cDatabase]): Connect to a MySql server.
Returns: .T. if connection was successful (.F. otherwise).

Delete( cTable, cWhere ): Delete rows based on 'cWhere' condition.
Returns: .T. if command was successfully executed (.F. otherwise).

Destroy(): Set all object variables to NIL, closes all workareas used by
'Select' method (if any) and disconnects.
Returns: NIL

Disconnect(): Disconnect from server.
Returns: NIL

Exec(cCommand): Executes a MySql command.
Returns: .T. if command was successfully executed (.F. otherwise).

Insert(cTable, aCols): Insert row. aCols, specifies cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

IsConnected(): Returns .T. if the current connection still alive, .F. if not.

New(): Object Initialization.
Returns: SELF (refers to the instance of the class that is being constructed).

Reconnect(). Attempts to re-connect using the current parameters.

RollBack(): Executes 'ROLLBACK' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Select(cSelect,cWorkArea): cSelect must be a MySql SELECT statement.
A recordset is created with the name specified as cWorkArea.
Returns: .T. if query was successful (.F. otherwise).

StartTransaction(): Executes 'START TRANSACTION' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Update(cTable,cWhere,aCols): Modify rows based on 'cWhere' condition. aCols, specifies
cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

Use(cDatabase): Selects the default database. Useful when connecting without
specifying a database or when working with multiple databases.
Returns: .T. if command was successfully executed (.F. otherwise).

VARIABLES:

cErrorDesc (Read Only): Error description (Empty if no error).

cMsgLang (Read Only): Current language for error/progress messages.

cNoQuoteChar: Set leftmost character indicator to instruct Update and Insert
methods to not quote a character value on aColumns
(cColumnName,xColumnValue) array (default value is '@').

lAutoReconnect: When set to .T. (the default value) operations that requires
connection to the server, will check if the connection still alive, if not,
reconnection will be attempted.

lError (Read Only): .T. if an error occured on last operation (.F. otherwise).

lShowMsgs: Determines if error/progress messages will be shown.

lTrace: When set to .T., a file called 'trace.log' containing last command
executed.

MariaDB:

Last years, for new projects (even local-data ones), I've used portable MariaDB.

It is compact, fast, reliable, secure and requires no installation.

You can download it at https://mariadb.org/download/ and select 'ZIP file' on
'Package Type'. You can unpack it at any place (<base_folder>).

For newer versions, prior to start MariaDB, you must initialize data directory:

<base_folder>\bin\mysql_install_db.exe --datadir=<base_folder>\data

Then you can run MariaDB:

<base_folder>\bin\mysqld.exe.

The default user is root with no password.

Best database utility: HeidiSQL (https://www.heidisql.com/)


I hope this be useful for someone.


Roberto.

Attachments

hmg.easy.sql.2025.08.26.zip (1789.69 KiB)
]]>

Changes on this Version (2025.08.26):

- New: SetLang(cLangId) method. Set library information messages language.
Useful when you do not want to use default language for messages
(current hb_langselect() setting).

Accepted values for <cLangId> are the following:

'EN' -> English
'ES' -> Spanish
'PT' -> Portuguese
'FR' -> French
'DE' -> German
'IT' -> Italian
'NL' -> Dutch
'SV' -> Swedish
'DA' -> Danish
'FI' -> Finnish
'NO' -> Norwegian
'HU' -> Hungarian

- New: 'lAutoReconnect' variable. When set to .T. (the default) operations that
requires connection to the server, on error, will check if the connection is still alive,
if not, reconnection will be attempted.

One BIG problem when working with some shared AMP hostings, are unexpected
disconnections. So, you could get frequent (and very frustrating)
'MySQL server has gone away' error messages.

To address this, I've added support for automatic handling of reconnections
to the library, so (hopefully) you should not care about this annoyance :D

- New: IsConnected() method. Returns .T. if the current connection still alive,
.F. if not.

- New: Reconnect() method. Attempts to re-connect using the current parameters.


This class must be considered EXPERIMENTAL.

My idea to start this library, was to have a wrapper for 'Simple SQL Interface' contribution by Mindaugas Kavaliauskas that I've used for many years.

This wrapper aims to have the following features:

- Handle all possible runtime error situations (bad parameters, connection, SQL syntax, etc.).

- Show all required progress information and error messages to the user.

- Handle simultaneous connections in an easy/intuitive way.

This is a very very basic documentation:

METHODS:

AffectedRows(): Returns the number of rows modified by the last executed
INSERT, UPDATE, or DELETE command.

CloseAreas(): Close all workareas open with 'Select' method (if any).
Returns: Number of workareas closed.

Commit(): Executes 'COMMIT' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Connect(cServer, cUser, cPassword [, cDatabase]): Connect to a MySql server.
Returns: .T. if connection was successful (.F. otherwise).

Delete( cTable, cWhere ): Delete rows based on 'cWhere' condition.
Returns: .T. if command was successfully executed (.F. otherwise).

Destroy(): Set all object variables to NIL, closes all workareas used by
'Select' method (if any) and disconnects.
Returns: NIL

Disconnect(): Disconnect from server.
Returns: NIL

Exec(cCommand): Executes a MySql command.
Returns: .T. if command was successfully executed (.F. otherwise).

Insert(cTable, aCols): Insert row. aCols, specifies cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

IsConnected(): Returns .T. if the current connection still alive, .F. if not.

New(): Object Initialization.
Returns: SELF (refers to the instance of the class that is being constructed).

Reconnect(). Attempts to re-connect using the current parameters.

RollBack(): Executes 'ROLLBACK' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Select(cSelect,cWorkArea): cSelect must be a MySql SELECT statement.
A recordset is created with the name specified as cWorkArea.
Returns: .T. if query was successful (.F. otherwise).

StartTransaction(): Executes 'START TRANSACTION' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Update(cTable,cWhere,aCols): Modify rows based on 'cWhere' condition. aCols, specifies
cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

Use(cDatabase): Selects the default database. Useful when connecting without
specifying a database or when working with multiple databases.
Returns: .T. if command was successfully executed (.F. otherwise).

VARIABLES:

cErrorDesc (Read Only): Error description (Empty if no error).

cMsgLang (Read Only): Current language for error/progress messages.

cNoQuoteChar: Set leftmost character indicator to instruct Update and Insert
methods to not quote a character value on aColumns
(cColumnName,xColumnValue) array (default value is '@').

lAutoReconnect: When set to .T. (the default value) operations that requires
connection to the server, will check if the connection still alive, if not,
reconnection will be attempted.

lError (Read Only): .T. if an error occured on last operation (.F. otherwise).

lShowMsgs: Determines if error/progress messages will be shown.

lTrace: When set to .T., a file called 'trace.log' containing last command
executed.

MariaDB:

Last years, for new projects (even local-data ones), I've used portable MariaDB.

It is compact, fast, reliable, secure and requires no installation.

You can download it at https://mariadb.org/download/ and select 'ZIP file' on
'Package Type'. You can unpack it at any place (<base_folder>).

For newer versions, prior to start MariaDB, you must initialize data directory:

<base_folder>\bin\mysql_install_db.exe --datadir=<base_folder>\data

Then you can run MariaDB:

<base_folder>\bin\mysqld.exe.

The default user is root with no password.

Best database utility: HeidiSQL (https://www.heidisql.com/)


I hope this be useful for someone.


Roberto.

Attachments

hmg.easy.sql.2025.08.26.zip (1789.69 KiB)
]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.08.26 :: Reply by serge_girard]]> 2025-08-26T06:07:30+00:00 2025-08-26T06:07:30+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7688&p=71875#p71875
Do you think it possible (for me) to use your project? I use MySQL for many years and all my programs have this construction:

Code: Select all

IF SQL_Connect()  == Nil	 
   MSGINFO('No database connection','NOK')
   RETURN
ENDIF

 
cQuery2 := 'SELECT CODE_DESC, CODE_VALUE  '  
cQuery2 += 'FROM CODE_TABLE ' 
cQuery2 += 'WHERE CODE = "KBO_LVC" '
cSQL2   := cQuery2
cQuery2	:= dbo:Query( cQuery2 )
IF cQuery2:NetErr()
   SQL_ERRORS(PROCNAME(), '4', cQuery2:Error(), cSQL2  )
   ? 'SQL ERROR  ' , cQuery2:Error(), cSQL2
   RETURN(FALSE)
ENDIF 
 
FOR nZZ := 1 To cQuery2:LastRec()
   aCurRow2      := cQuery2:GetRow(nZZ)
   cCODE_DESC    := aCurRow2:fieldGet(1)             
   cCODE_VALUE   := aCurRow2:fieldGet(2)   
   // action
   cQuery3 := 'INSERTO INTO ........... '  
   cQuery3	:= dbo:Query( cQuery3 )
   /*
   ETC..
   */
NEXT nZZ 

SQL_DisConnect()
RETURN







FUNCTION SQL_Connect()
/**********************************************/
LOCAL cQuery2, cSQL2  

IF xINP_PARAM == 'T'  // TEST HOST
	xDB_NAME		:= 'SG_TEST'    
	xDB_HOST		:= 'axc.nl'     
	xDB_USER		:= 'TSG_TEST'    
	xDB_PW		:= 'tabracadabra'     
ELSE
	xDB_NAME		:= 'SG_PROD'   
	xDB_HOST		:= 'axc.nl'     
	xDB_USER		:= 'PSG_TEST'    
	xDB_PW		:= 'pabracadabra'     
ENDIF
 
dbo := tmysqlserver():new(STRVALUE(xDB_HOST),STRVALUE(xDB_USER),STRVALUE(xDB_PW))
IF dbo:NetErr()
   MSGINFO('Call me')
   RETURN nil
ENDIF

IF!EMPTY(xDB_NAME) 
   dbo:selectdb(xDB_NAME)
   IF dbo:NetErr()
      MSGINFO('Call me')
      RETURN nil
   ENDIF
ENDIF

cQuery2 := "SET NAMES 'utf8mb4' "
cSQL2   := cQuery2
cQuery2	:= dbo:Query( cQuery2 )
IF cQuery2:NetErr()
   SQL_ERRORS(PROCNAME(), '1', cQuery2:Error(), cSQL2  )   
   RETURN(FALSE)
ENDIF 

RETURN dbo



FUNCTION SQL_Disconnect()
/************************/
dbo:Destroy()
RETURN

Of course I don't want to rewrite tons of lines.... Is it possible?

Serge]]>

Do you think it possible (for me) to use your project? I use MySQL for many years and all my programs have this construction:

Code: Select all

IF SQL_Connect()  == Nil	 
   MSGINFO('No database connection','NOK')
   RETURN
ENDIF

 
cQuery2 := 'SELECT CODE_DESC, CODE_VALUE  '  
cQuery2 += 'FROM CODE_TABLE ' 
cQuery2 += 'WHERE CODE = "KBO_LVC" '
cSQL2   := cQuery2
cQuery2	:= dbo:Query( cQuery2 )
IF cQuery2:NetErr()
   SQL_ERRORS(PROCNAME(), '4', cQuery2:Error(), cSQL2  )
   ? 'SQL ERROR  ' , cQuery2:Error(), cSQL2
   RETURN(FALSE)
ENDIF 
 
FOR nZZ := 1 To cQuery2:LastRec()
   aCurRow2      := cQuery2:GetRow(nZZ)
   cCODE_DESC    := aCurRow2:fieldGet(1)             
   cCODE_VALUE   := aCurRow2:fieldGet(2)   
   // action
   cQuery3 := 'INSERTO INTO ........... '  
   cQuery3	:= dbo:Query( cQuery3 )
   /*
   ETC..
   */
NEXT nZZ 

SQL_DisConnect()
RETURN







FUNCTION SQL_Connect()
/**********************************************/
LOCAL cQuery2, cSQL2  

IF xINP_PARAM == 'T'  // TEST HOST
	xDB_NAME		:= 'SG_TEST'    
	xDB_HOST		:= 'axc.nl'     
	xDB_USER		:= 'TSG_TEST'    
	xDB_PW		:= 'tabracadabra'     
ELSE
	xDB_NAME		:= 'SG_PROD'   
	xDB_HOST		:= 'axc.nl'     
	xDB_USER		:= 'PSG_TEST'    
	xDB_PW		:= 'pabracadabra'     
ENDIF
 
dbo := tmysqlserver():new(STRVALUE(xDB_HOST),STRVALUE(xDB_USER),STRVALUE(xDB_PW))
IF dbo:NetErr()
   MSGINFO('Call me')
   RETURN nil
ENDIF

IF!EMPTY(xDB_NAME) 
   dbo:selectdb(xDB_NAME)
   IF dbo:NetErr()
      MSGINFO('Call me')
      RETURN nil
   ENDIF
ENDIF

cQuery2 := "SET NAMES 'utf8mb4' "
cSQL2   := cQuery2
cQuery2	:= dbo:Query( cQuery2 )
IF cQuery2:NetErr()
   SQL_ERRORS(PROCNAME(), '1', cQuery2:Error(), cSQL2  )   
   RETURN(FALSE)
ENDIF 

RETURN dbo



FUNCTION SQL_Disconnect()
/************************/
dbo:Destroy()
RETURN

Of course I don't want to rewrite tons of lines.... Is it possible?

Serge]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.08.26 :: Reply by Roberto Lopez]]> 2025-08-26T13:17:23+00:00 2025-08-26T13:17:23+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7688&p=71876#p71876
serge_girard wrote: Tue Aug 26, 2025 6:07 am Thanks Roberto !

Do you think it possible (for me) to use your project? I use MySQL for many years and all my programs have this construction:
Hi Serge!

Easy.Sql has a very different approach, focused on minimize code writing and automation of many task, so, I'm afraid yes, your code will required a lot of changes to make it work with Easy.Sql.

If you want to minimize the required changes, consider using Exec(cCommand) method, so porting your code could be easier, but loosing many of Easy.Sql advantages.]]>
serge_girard wrote: Tue Aug 26, 2025 6:07 am Thanks Roberto !

Do you think it possible (for me) to use your project? I use MySQL for many years and all my programs have this construction:
Hi Serge!

Easy.Sql has a very different approach, focused on minimize code writing and automation of many task, so, I'm afraid yes, your code will required a lot of changes to make it work with Easy.Sql.

If you want to minimize the required changes, consider using Exec(cCommand) method, so porting your code could be easier, but loosing many of Easy.Sql advantages.]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.08.26 :: Reply by serge_girard]]> 2025-08-26T13:30:34+00:00 2025-08-26T13:30:34+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7688&p=71878#p71878
Thanks for replying.
Maybe then in some other life...!

Serge]]>

Thanks for replying.
Maybe then in some other life...!

Serge]]>
<![CDATA[HMG Samples :: HMG.EASY.SQL.2025.09.04 :: Author Roberto Lopez]]> 2025-09-03T22:24:41+00:00 2025-09-03T22:24:41+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7694&p=71887#p71887
Changelog:

- New: Report(cQuery,cTitle,aHeaders,aWidths,aJustify,cPdfName,lPreview,aFormats) method.
Creates a PDF report from a MySql Query.
Returns: .T. if it was successful (.F. otherwise).

For PDF generation it uses a slightly modified version of the original HMG_HPDF by
Rathinagiri. I've renamed the source file and internal functions to avoid conflicts
with any other version of it.

Example:

Code: Select all

	cCommand := 'SELECT code,description,location,stock,price FROM hmgtest ORDER BY code'
	cTitle	 := 'STOCK REPORT'
	aHeaders := { 'CODE', 'DESCRIPTION', 'LOCATION', 'STOCK', 'PRICE' }
	aWidths	 := { 6,32,32,6,12 }
	aJustify := { 'C','L', 'L','R','R'}
	cPdfName := 'stock' + '.' + dtos(date()) + '_' + alltrim(str(int(seconds())))
	lPreview := .t.
	aFormats := { {|x| STRZERO(x,4)},{|x|UPPER(x)},{|x|UPPER(x)},NIL,{|x|TRANSFORM(x,'999,999.99')} }

	IF !:Report(cCommand,cTitle,aHeaders,aWidths,aJustify,cPdfName,lPreview,aFormats)
		RETURN
	ENDIF

- New: Export(cQuery,cOutFile,aFormats,cDelimiter,lQuote) method.
Creates a CSV file from a MySql Query.
Returns: .T. if it was successful (.F. otherwise).

Example:

Code: Select all

		cQuery   := 'SELECT * FROM hmgtest ORDER BY code'
		cOutFile := 'hmgtest.csv'
		
		* aFormats (optional)

		aFormats := { {|x| STRZERO(x, 4)},{|x| STRZERO(x, 4)}, {|x| UPPER(x) },NIL,NIL,{|x| TRANSFORM(x,'999,999.99') } }

		* cDelimiter is optional (default is ';')

		cDelimiter := NIL

		* Quote is optional (default is .F.)

		lQuote := NIL
		
		IF !:Export(cQuery,cOutFile,aFormats,cDelimiter,lQuote)
			RETURN
		ENDIF

I hope this be useful for someone.

Attachments

hmg.easy.sql.2025.09.04.zip (2003.33 KiB)
]]>

Changelog:

- New: Report(cQuery,cTitle,aHeaders,aWidths,aJustify,cPdfName,lPreview,aFormats) method.
Creates a PDF report from a MySql Query.
Returns: .T. if it was successful (.F. otherwise).

For PDF generation it uses a slightly modified version of the original HMG_HPDF by
Rathinagiri. I've renamed the source file and internal functions to avoid conflicts
with any other version of it.

Example:

Code: Select all

	cCommand := 'SELECT code,description,location,stock,price FROM hmgtest ORDER BY code'
	cTitle	 := 'STOCK REPORT'
	aHeaders := { 'CODE', 'DESCRIPTION', 'LOCATION', 'STOCK', 'PRICE' }
	aWidths	 := { 6,32,32,6,12 }
	aJustify := { 'C','L', 'L','R','R'}
	cPdfName := 'stock' + '.' + dtos(date()) + '_' + alltrim(str(int(seconds())))
	lPreview := .t.
	aFormats := { {|x| STRZERO(x,4)},{|x|UPPER(x)},{|x|UPPER(x)},NIL,{|x|TRANSFORM(x,'999,999.99')} }

	IF !:Report(cCommand,cTitle,aHeaders,aWidths,aJustify,cPdfName,lPreview,aFormats)
		RETURN
	ENDIF

- New: Export(cQuery,cOutFile,aFormats,cDelimiter,lQuote) method.
Creates a CSV file from a MySql Query.
Returns: .T. if it was successful (.F. otherwise).

Example:

Code: Select all

		cQuery   := 'SELECT * FROM hmgtest ORDER BY code'
		cOutFile := 'hmgtest.csv'
		
		* aFormats (optional)

		aFormats := { {|x| STRZERO(x, 4)},{|x| STRZERO(x, 4)}, {|x| UPPER(x) },NIL,NIL,{|x| TRANSFORM(x,'999,999.99') } }

		* cDelimiter is optional (default is ';')

		cDelimiter := NIL

		* Quote is optional (default is .F.)

		lQuote := NIL
		
		IF !:Export(cQuery,cOutFile,aFormats,cDelimiter,lQuote)
			RETURN
		ENDIF

I hope this be useful for someone.

Attachments

hmg.easy.sql.2025.09.04.zip (2003.33 KiB)
]]>
<![CDATA[HMG Samples :: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Author Roberto Lopez]]> 2025-08-31T19:03:04+00:00 2025-08-31T19:03:04+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71879#p71879
Changes on this Version (2025.09.01):

- Modified: 'Select' method. Second parameter can now (optionally) be a reference to a
standard or hash array. This array (if specified) will receive the resulting
recordset in the corresponding format (standard or hash).
In addition, two new optional parameters, allows to specify a grid and window
names to automatically fill it with the resulting recordset. In this case,
the second parameter is optional.
If grid is specified an additional parameter can be specified (codeblocks array)
for formating.

Hash array example...

Code: Select all

hRows := {=>} ; hRow := NIL
oSql:Select('SELECT * FROM hmgtest ORDER BY code', @hRows)
Fill a grid with the result...

Code: Select all

FOR EACH hRow IN hRows
Test.Grid_1.AddItem({ StrZero(hRow["code"],4), AllTrim(hRow["description"]), AllTrim(hRow["location"]), AllTrim(Str(hRow["stock"])), AllTrim(Str(hRow["price"])) } )
NEXT
Direct to grid with no Second parameter example...

Code: Select all

oSql:Select('SELECT * FROM hmgtest ORDER BY code',, 'Grid_1', 'Test')
As previous with formatting...

Code: Select all

aFmt := { ;
	NIL, ; 
	{|x| STRZERO( x, 4) } , ; 
	{|x| UPPER( x ) } , ; 
	NIL, ; 
	NIL , ; 
	{|x| TRANSFORM( x ,'999,999.99' ) } ;
	}

oSql:Select('SELECT * FROM hmgtest ORDER BY code',,'Grid_1','Test',aFmt)
- New: 'nErrorNo' variable. Contains current error code.

- New: GetLastInsertId() method. Return last AUTO_INCREMENT on INSERT.

- Fixed: Various problems with error processing.

- Modified: Demo, showing new features.


This class must be considered EXPERIMENTAL.

My idea to start this library, was to have a wrapper for 'Simple SQL Interface' contribution by Mindaugas Kavaliauskas that I've used for many years.

This wrapper aims to have the following features:

- Handle all possible runtime error situations (bad parameters, connection, SQL syntax, etc.).

- Show all required progress information and error messages to the user.

- Handle simultaneous connections in an easy/intuitive way.


This is a very very basic documentation:


METHODS:

AffectedRows(): Returns the number of rows modified by the last executed
INSERT, UPDATE, or DELETE command.

CloseAreas(): Close all workareas open with 'Select' method (if any).
Returns: Number of workareas closed.

Commit(): Executes 'COMMIT' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Connect(cServer, cUser, cPassword [, cDatabase]): Connect to a MySql server.
Returns: .T. if connection was successful (.F. otherwise).

Delete( cTable, cWhere ): Delete rows based on 'cWhere' condition.
Returns: .T. if command was successfully executed (.F. otherwise).

Destroy(): Set all object variables to NIL, closes all workareas used by
'Select' method (if any) and disconnects.
Returns: NIL

Disconnect(): Disconnect from server.
Returns: NIL

Exec(cCommand): Executes a MySql command.
Returns: .T. if command was successfully executed (.F. otherwise).

GetLastInsertId(): Returns last AUTO_INCREMENT on INSERT.

Insert(cTable, aCols): Insert row. aCols, specifies cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

IsConnected(): Returns .T. if the current connection still alive, .F. if not.

New(): Object Initialization.
Returns: SELF (refers to the instance of the class that is being constructed).

Reconnect(). Attempts to re-connect using the current parameters.
Returns: .T. if command was successfully executed (.F. otherwise).

RollBack(): Executes 'ROLLBACK' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Select(cCommand,[cWorkArea|@aArray|@hHash],[cGridName,cWindowName][,abFormats]):
cCommand must be a MySql SELECT statement.
If cWorkArea is specified a new workarea will be created containing the
query result. If you, instead, specifies a reference to an array
(or hash array), the resulting recordset will be stored there in the
corresponding format.
If cGridName and cWindowName are specified, a grid will be filled with the
resulting recordset. In this case, second parameter (cWorkArea, aArray or
hArray) is optional.
If grid is specified an additional parameter can be specified (codeblocks array)
for formating.
Returns: .T. if query was successful (.F. otherwise).

StartTransaction(): Executes 'START TRANSACTION' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Update(cTable,cWhere,aCols): Modify rows based on 'cWhere' condition. aCols, specifies
cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

Use(cDatabase): Selects the default database. Useful when connecting without
specifying a database or when working with multiple databases.
Returns: .T. if command was successfully executed (.F. otherwise).


VARIABLES:

cErrorDesc (Read Only): Error description (Empty if no error).

cMsgLang (Read Only): Current language for error/progress messages.

cNoQuoteChar: Set leftmost character indicator to instruct Update and Insert
methods to not quote a character value on aColumns
(cColumnName,xColumnValue) array (default value is '@').

lAutoReconnect: When set to .T. (the default value) operations that requires
connection to the server, will check if the connection still alive, if not,
reconnection will be attempted.

lError (Read Only): .T. if an error occured on last operation (.F. otherwise).

lShowMsgs: Determines if error/progress messages will be shown.

lTrace: When set to .T., a file called 'trace.log' containing last command
executed.

nErrorNo (Read Only) Current error code.


MariaDB:

Last years, for new projects (even local-data ones), I've used portable MariaDB.

It is compact, fast, reliable, secure and requires no installation.

You can download it at https://mariadb.org/download/ and select 'ZIP file' on
'Package Type'. You can unpack it at any place (<base_folder>).

For newer versions, prior to start MariaDB, you must initialize data directory:

<base_folder>\bin\mysql_install_db.exe --datadir=<base_folder>\data

Then you can run MariaDB:

<base_folder>\bin\mysqld.exe.

The default user is root with no password.

Best database utility: HeidiSQL (https://www.heidisql.com/)


I hope this be useful for someone.


Roberto.

Attachments

hmg.easy.sql.2025.09.01.zip (1797.55 KiB)
]]>

Changes on this Version (2025.09.01):

- Modified: 'Select' method. Second parameter can now (optionally) be a reference to a
standard or hash array. This array (if specified) will receive the resulting
recordset in the corresponding format (standard or hash).
In addition, two new optional parameters, allows to specify a grid and window
names to automatically fill it with the resulting recordset. In this case,
the second parameter is optional.
If grid is specified an additional parameter can be specified (codeblocks array)
for formating.

Hash array example...

Code: Select all

hRows := {=>} ; hRow := NIL
oSql:Select('SELECT * FROM hmgtest ORDER BY code', @hRows)
Fill a grid with the result...

Code: Select all

FOR EACH hRow IN hRows
Test.Grid_1.AddItem({ StrZero(hRow["code"],4), AllTrim(hRow["description"]), AllTrim(hRow["location"]), AllTrim(Str(hRow["stock"])), AllTrim(Str(hRow["price"])) } )
NEXT
Direct to grid with no Second parameter example...

Code: Select all

oSql:Select('SELECT * FROM hmgtest ORDER BY code',, 'Grid_1', 'Test')
As previous with formatting...

Code: Select all

aFmt := { ;
	NIL, ; 
	{|x| STRZERO( x, 4) } , ; 
	{|x| UPPER( x ) } , ; 
	NIL, ; 
	NIL , ; 
	{|x| TRANSFORM( x ,'999,999.99' ) } ;
	}

oSql:Select('SELECT * FROM hmgtest ORDER BY code',,'Grid_1','Test',aFmt)
- New: 'nErrorNo' variable. Contains current error code.

- New: GetLastInsertId() method. Return last AUTO_INCREMENT on INSERT.

- Fixed: Various problems with error processing.

- Modified: Demo, showing new features.


This class must be considered EXPERIMENTAL.

My idea to start this library, was to have a wrapper for 'Simple SQL Interface' contribution by Mindaugas Kavaliauskas that I've used for many years.

This wrapper aims to have the following features:

- Handle all possible runtime error situations (bad parameters, connection, SQL syntax, etc.).

- Show all required progress information and error messages to the user.

- Handle simultaneous connections in an easy/intuitive way.


This is a very very basic documentation:


METHODS:

AffectedRows(): Returns the number of rows modified by the last executed
INSERT, UPDATE, or DELETE command.

CloseAreas(): Close all workareas open with 'Select' method (if any).
Returns: Number of workareas closed.

Commit(): Executes 'COMMIT' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Connect(cServer, cUser, cPassword [, cDatabase]): Connect to a MySql server.
Returns: .T. if connection was successful (.F. otherwise).

Delete( cTable, cWhere ): Delete rows based on 'cWhere' condition.
Returns: .T. if command was successfully executed (.F. otherwise).

Destroy(): Set all object variables to NIL, closes all workareas used by
'Select' method (if any) and disconnects.
Returns: NIL

Disconnect(): Disconnect from server.
Returns: NIL

Exec(cCommand): Executes a MySql command.
Returns: .T. if command was successfully executed (.F. otherwise).

GetLastInsertId(): Returns last AUTO_INCREMENT on INSERT.

Insert(cTable, aCols): Insert row. aCols, specifies cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

IsConnected(): Returns .T. if the current connection still alive, .F. if not.

New(): Object Initialization.
Returns: SELF (refers to the instance of the class that is being constructed).

Reconnect(). Attempts to re-connect using the current parameters.
Returns: .T. if command was successfully executed (.F. otherwise).

RollBack(): Executes 'ROLLBACK' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Select(cCommand,[cWorkArea|@aArray|@hHash],[cGridName,cWindowName][,abFormats]):
cCommand must be a MySql SELECT statement.
If cWorkArea is specified a new workarea will be created containing the
query result. If you, instead, specifies a reference to an array
(or hash array), the resulting recordset will be stored there in the
corresponding format.
If cGridName and cWindowName are specified, a grid will be filled with the
resulting recordset. In this case, second parameter (cWorkArea, aArray or
hArray) is optional.
If grid is specified an additional parameter can be specified (codeblocks array)
for formating.
Returns: .T. if query was successful (.F. otherwise).

StartTransaction(): Executes 'START TRANSACTION' command.
Returns: .T. if command was successfully executed (.F. otherwise).

Update(cTable,cWhere,aCols): Modify rows based on 'cWhere' condition. aCols, specifies
cColumnname => xData pairs (hash array).
Returns: .T. if command was successfully executed (.F. otherwise).

Use(cDatabase): Selects the default database. Useful when connecting without
specifying a database or when working with multiple databases.
Returns: .T. if command was successfully executed (.F. otherwise).


VARIABLES:

cErrorDesc (Read Only): Error description (Empty if no error).

cMsgLang (Read Only): Current language for error/progress messages.

cNoQuoteChar: Set leftmost character indicator to instruct Update and Insert
methods to not quote a character value on aColumns
(cColumnName,xColumnValue) array (default value is '@').

lAutoReconnect: When set to .T. (the default value) operations that requires
connection to the server, will check if the connection still alive, if not,
reconnection will be attempted.

lError (Read Only): .T. if an error occured on last operation (.F. otherwise).

lShowMsgs: Determines if error/progress messages will be shown.

lTrace: When set to .T., a file called 'trace.log' containing last command
executed.

nErrorNo (Read Only) Current error code.


MariaDB:

Last years, for new projects (even local-data ones), I've used portable MariaDB.

It is compact, fast, reliable, secure and requires no installation.

You can download it at https://mariadb.org/download/ and select 'ZIP file' on
'Package Type'. You can unpack it at any place (<base_folder>).

For newer versions, prior to start MariaDB, you must initialize data directory:

<base_folder>\bin\mysql_install_db.exe --datadir=<base_folder>\data

Then you can run MariaDB:

<base_folder>\bin\mysqld.exe.

The default user is root with no password.

Best database utility: HeidiSQL (https://www.heidisql.com/)


I hope this be useful for someone.


Roberto.

Attachments

hmg.easy.sql.2025.09.01.zip (1797.55 KiB)
]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by tonton2]]> 2025-09-01T10:40:28+00:00 2025-09-01T10:40:28+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71880#p71880 j'ai installé MariaDB et j'ai aussi mysql , mais je n'arrive a créer la base de donnée hmgData .ça me donne :"connexion error", je dois avoir manqué quelque chose
Traduction Google
I installed MariaDB and I also have mysql, but I can't create the hmgData database. It gives me: "connection error", I must have missed something]]>
j'ai installé MariaDB et j'ai aussi mysql , mais je n'arrive a créer la base de donnée hmgData .ça me donne :"connexion error", je dois avoir manqué quelque chose
Traduction Google
I installed MariaDB and I also have mysql, but I can't create the hmgData database. It gives me: "connection error", I must have missed something]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by Roberto Lopez]]> 2025-09-01T13:32:26+00:00 2025-09-01T13:32:26+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71881#p71881
tonton2 wrote: Mon Sep 01, 2025 10:40 am Bonjour,
j'ai installé MariaDB et j'ai aussi mysql , mais je n'arrive a créer la base de donnée hmgData .ça me donne :"connexion error", je dois avoir manqué quelque chose
Traduction Google
I installed MariaDB and I also have mysql, but I can't create the hmgData database. It gives me: "connection error", I must have missed something
Hi,

If do you have two installations (MariaDb and Mysql) that could be the problem...

Be sure that you have only one installation and then attempt to connect with Heidi (heidisql.com). If you can connect with Heidi you should be able to connect with the provided demo too.]]>
tonton2 wrote: Mon Sep 01, 2025 10:40 am Bonjour,
j'ai installé MariaDB et j'ai aussi mysql , mais je n'arrive a créer la base de donnée hmgData .ça me donne :"connexion error", je dois avoir manqué quelque chose
Traduction Google
I installed MariaDB and I also have mysql, but I can't create the hmgData database. It gives me: "connection error", I must have missed something
Hi,

If do you have two installations (MariaDb and Mysql) that could be the problem...

Be sure that you have only one installation and then attempt to connect with Heidi (heidisql.com). If you can connect with Heidi you should be able to connect with the provided demo too.]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by vagblad]]> 2025-09-03T12:22:52+00:00 2025-09-03T12:22:52+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71886#p71886
tonton2 wrote: Mon Sep 01, 2025 10:40 am Bonjour,
j'ai installé MariaDB et j'ai aussi mysql , mais je n'arrive a créer la base de donnée hmgData .ça me donne :"connexion error", je dois avoir manqué quelque chose
Traduction Google
I installed MariaDB and I also have mysql, but I can't create the hmgData database. It gives me: "connection error", I must have missed something
You can have both installed and run both server instances at the same time but they should be running on different ports. So check your connection method for the correct port for either of them. Default port is usually 3306 for both of them.]]>
tonton2 wrote: Mon Sep 01, 2025 10:40 am Bonjour,
j'ai installé MariaDB et j'ai aussi mysql , mais je n'arrive a créer la base de donnée hmgData .ça me donne :"connexion error", je dois avoir manqué quelque chose
Traduction Google
I installed MariaDB and I also have mysql, but I can't create the hmgData database. It gives me: "connection error", I must have missed something
You can have both installed and run both server instances at the same time but they should be running on different ports. So check your connection method for the correct port for either of them. Default port is usually 3306 for both of them.]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by mol]]> 2025-09-10T19:24:09+00:00 2025-09-10T19:24:09+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71897#p71897 Do you have a good working method to do it?]]> Do you have a good working method to do it?]]> <![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by martingz]]> 2025-09-11T02:53:34+00:00 2025-09-11T02:53:34+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71898#p71898
varfoto:=File_To_Buff(altaempleado.image_1.picture)
query:= "Update Empleados set foto=' " + varfoto + "' where id=" + str(varid)



Function File_To_Buff(cFile)
local cBuff:="", fh, nLen
local lRetVal:=.f.
local cFile_in := cFile
fh:=fopen(cFile_in,0)
if fh > -1
nLen:= fseek(fh, 0, 2)
if nLen > 0
fseek(fh, 0, 0)
cBuff:=space(nLen)
fread(fh, @cBuff, nLen)
cBuff:=strtran(cBuff, chr(92), "\\")
cBuff:=strtran(cBuff, chr(0), "\0")
cBuff:=strtran(cBuff, chr(39), "\'")
cBuff:=strtran(cBuff, chr(34), '\"')
endif
else
cBuff := ""
endif
fclose(fh)
Return(cBuff)]]>

varfoto:=File_To_Buff(altaempleado.image_1.picture)
query:= "Update Empleados set foto=' " + varfoto + "' where id=" + str(varid)



Function File_To_Buff(cFile)
local cBuff:="", fh, nLen
local lRetVal:=.f.
local cFile_in := cFile
fh:=fopen(cFile_in,0)
if fh > -1
nLen:= fseek(fh, 0, 2)
if nLen > 0
fseek(fh, 0, 0)
cBuff:=space(nLen)
fread(fh, @cBuff, nLen)
cBuff:=strtran(cBuff, chr(92), "\\")
cBuff:=strtran(cBuff, chr(0), "\0")
cBuff:=strtran(cBuff, chr(39), "\'")
cBuff:=strtran(cBuff, chr(34), '\"')
endif
else
cBuff := ""
endif
fclose(fh)
Return(cBuff)]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by mol]]> 2025-09-11T06:15:13+00:00 2025-09-11T06:15:13+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71899#p71899 But I have a problem, application is written in CodePage 1250 and server is installed on Debian with Collate UTF8.
To transfer image content, I need to convert it to utf-8 string. It increases size of field about 1,5 times
I need to avoid this size increment]]>
But I have a problem, application is written in CodePage 1250 and server is installed on Debian with Collate UTF8.
To transfer image content, I need to convert it to utf-8 string. It increases size of field about 1,5 times
I need to avoid this size increment]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by srvet_claudio]]> 2025-09-11T23:23:14+00:00 2025-09-11T23:23:14+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71902#p71902 try convert image into string base64.

base64.hbp

Code: Select all

base64.prg
-lcrypt32
base64.prg

Code: Select all

#include "hmg.ch"

FUNCTION Main
   LOCAL cBase64, lOk

   // Convert file into Base64 string
   cBase64 := FileToBase64( "BosTaurus_logo.PNG" )

   IF Empty( cBase64 )
      MsgInfo( "Error converting to Base64" )
      RETURN NIL
   ENDIF

   MsgInfo( "Base64 generated (first 100 chars): " + Left( cBase64, 100 ) + "..." )

   hb_memowrit("BosTaurus_logo.txt", cBase64)

   // Rebuild file from Base64 string
   lOk := Base64ToFile( cBase64, "Rebuild.PNG" )

   IF lOk
      MsgInfo( "File rebuilt ok" )
   ELSE
      MsgInfo( "Error rebuilding file" )
   ENDIF

RETURN NIL


#pragma BEGINDUMP

#define UNICODE

#include <windows.h>
#include <wincrypt.h>
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapierr.h"
#include "hbmemory.ch"

// --- FILETOBASE64 ---
// Convert a binary file into a Base64 string
// Harbour: FileToBase64( <cFileName> ) -> <cBase64>
HB_FUNC( FILETOBASE64 )
{
   const char * filename = hb_parc( 1 );
   FILE * file = fopen( filename, "rb" );
   if( !file )
   {
      hb_retc( "" );
      return;
   }

   // Get file size
   fseek( file, 0, SEEK_END );
   long filesize = ftell( file );
   rewind( file );

   // Allocate buffer and read file
   BYTE * buffer = (BYTE*) hb_xgrab( filesize );
   fread( buffer, 1, filesize, file );
   fclose( file );

   DWORD base64Len = 0;

   // First call to get required size
   CryptBinaryToStringW( buffer, filesize, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &base64Len );
   WCHAR * base64W = (WCHAR*) hb_xgrab( base64Len * sizeof(WCHAR) );

   // Second call does the actual conversion
   if( CryptBinaryToStringW( buffer, filesize, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64W, &base64Len ) )
   {
      // Convert wide string to UTF-8 (Harbour uses UTF-8 internally)
      int len = WideCharToMultiByte( CP_UTF8, 0, base64W, -1, NULL, 0, NULL, NULL );
      char * utf8 = (char*) hb_xgrab( len );
      WideCharToMultiByte( CP_UTF8, 0, base64W, -1, utf8, len, NULL, NULL );
      hb_retc( utf8 );
      hb_xfree( utf8 );
   }
   else
      hb_retc( "" );

   hb_xfree( base64W );
   hb_xfree( buffer );
}

// --- BASE64TOFILE ---
// Convert a Base64 string back to a binary file
// Harbour: Base64ToFile( <cBase64>, <cOutputFile> ) -> <lSuccess>
HB_FUNC( BASE64TOFILE )
{
   const char * base64 = hb_parc( 1 );
   const char * outname = hb_parc( 2 );
   DWORD binLen = 0;

   // Convert UTF-8 Harbour string to wide string
   int wideLen = MultiByteToWideChar( CP_UTF8, 0, base64, -1, NULL, 0 );
   WCHAR * base64W = (WCHAR*) hb_xgrab( wideLen * sizeof(WCHAR) );
   MultiByteToWideChar( CP_UTF8, 0, base64, -1, base64W, wideLen );

   // First call to get required binary size
   if( !CryptStringToBinaryW( base64W, 0, CRYPT_STRING_BASE64, NULL, &binLen, NULL, NULL ) )
   {
      hb_xfree( base64W );
      hb_retl( FALSE );
      return;
   }

   BYTE * buffer = (BYTE*) hb_xgrab( binLen );

   // Second call does the actual conversion
   if( !CryptStringToBinaryW( base64W, 0, CRYPT_STRING_BASE64, buffer, &binLen, NULL, NULL ) )
   {
      hb_xfree( base64W );
      hb_xfree( buffer );
      hb_retl( FALSE );
      return;
   }

   hb_xfree( base64W );

   // Write buffer to output file
   FILE * file = fopen( outname, "wb" );
   if( !file )
   {
      hb_xfree( buffer );
      hb_retl( FALSE );
      return;
   }

   fwrite( buffer, 1, binLen, file );
   fclose( file );
   hb_xfree( buffer );

   hb_retl( TRUE );
}

#pragma ENDDUMP

]]>
try convert image into string base64.

base64.hbp

Code: Select all

base64.prg
-lcrypt32
base64.prg

Code: Select all

#include "hmg.ch"

FUNCTION Main
   LOCAL cBase64, lOk

   // Convert file into Base64 string
   cBase64 := FileToBase64( "BosTaurus_logo.PNG" )

   IF Empty( cBase64 )
      MsgInfo( "Error converting to Base64" )
      RETURN NIL
   ENDIF

   MsgInfo( "Base64 generated (first 100 chars): " + Left( cBase64, 100 ) + "..." )

   hb_memowrit("BosTaurus_logo.txt", cBase64)

   // Rebuild file from Base64 string
   lOk := Base64ToFile( cBase64, "Rebuild.PNG" )

   IF lOk
      MsgInfo( "File rebuilt ok" )
   ELSE
      MsgInfo( "Error rebuilding file" )
   ENDIF

RETURN NIL


#pragma BEGINDUMP

#define UNICODE

#include <windows.h>
#include <wincrypt.h>
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapierr.h"
#include "hbmemory.ch"

// --- FILETOBASE64 ---
// Convert a binary file into a Base64 string
// Harbour: FileToBase64( <cFileName> ) -> <cBase64>
HB_FUNC( FILETOBASE64 )
{
   const char * filename = hb_parc( 1 );
   FILE * file = fopen( filename, "rb" );
   if( !file )
   {
      hb_retc( "" );
      return;
   }

   // Get file size
   fseek( file, 0, SEEK_END );
   long filesize = ftell( file );
   rewind( file );

   // Allocate buffer and read file
   BYTE * buffer = (BYTE*) hb_xgrab( filesize );
   fread( buffer, 1, filesize, file );
   fclose( file );

   DWORD base64Len = 0;

   // First call to get required size
   CryptBinaryToStringW( buffer, filesize, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &base64Len );
   WCHAR * base64W = (WCHAR*) hb_xgrab( base64Len * sizeof(WCHAR) );

   // Second call does the actual conversion
   if( CryptBinaryToStringW( buffer, filesize, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64W, &base64Len ) )
   {
      // Convert wide string to UTF-8 (Harbour uses UTF-8 internally)
      int len = WideCharToMultiByte( CP_UTF8, 0, base64W, -1, NULL, 0, NULL, NULL );
      char * utf8 = (char*) hb_xgrab( len );
      WideCharToMultiByte( CP_UTF8, 0, base64W, -1, utf8, len, NULL, NULL );
      hb_retc( utf8 );
      hb_xfree( utf8 );
   }
   else
      hb_retc( "" );

   hb_xfree( base64W );
   hb_xfree( buffer );
}

// --- BASE64TOFILE ---
// Convert a Base64 string back to a binary file
// Harbour: Base64ToFile( <cBase64>, <cOutputFile> ) -> <lSuccess>
HB_FUNC( BASE64TOFILE )
{
   const char * base64 = hb_parc( 1 );
   const char * outname = hb_parc( 2 );
   DWORD binLen = 0;

   // Convert UTF-8 Harbour string to wide string
   int wideLen = MultiByteToWideChar( CP_UTF8, 0, base64, -1, NULL, 0 );
   WCHAR * base64W = (WCHAR*) hb_xgrab( wideLen * sizeof(WCHAR) );
   MultiByteToWideChar( CP_UTF8, 0, base64, -1, base64W, wideLen );

   // First call to get required binary size
   if( !CryptStringToBinaryW( base64W, 0, CRYPT_STRING_BASE64, NULL, &binLen, NULL, NULL ) )
   {
      hb_xfree( base64W );
      hb_retl( FALSE );
      return;
   }

   BYTE * buffer = (BYTE*) hb_xgrab( binLen );

   // Second call does the actual conversion
   if( !CryptStringToBinaryW( base64W, 0, CRYPT_STRING_BASE64, buffer, &binLen, NULL, NULL ) )
   {
      hb_xfree( base64W );
      hb_xfree( buffer );
      hb_retl( FALSE );
      return;
   }

   hb_xfree( base64W );

   // Write buffer to output file
   FILE * file = fopen( outname, "wb" );
   if( !file )
   {
      hb_xfree( buffer );
      hb_retl( FALSE );
      return;
   }

   fwrite( buffer, 1, binLen, file );
   fclose( file );
   hb_xfree( buffer );

   hb_retl( TRUE );
}

#pragma ENDDUMP

]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by mol]]> 2025-09-12T08:03:59+00:00 2025-09-12T08:03:59+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71903#p71903 Converting to BASE64 increases size of field, eg. from 9605 bytes to 12808.
It works fine for sending file.

But, I'm still searching a way to insert file without increasing place occupation.
Maybe is there a method to send binary file to f***d postgresql server (I really don't like it, but my client is stubborn).

It's possible with python, but I don't want to mix harbour with python.]]>
Converting to BASE64 increases size of field, eg. from 9605 bytes to 12808.
It works fine for sending file.

But, I'm still searching a way to insert file without increasing place occupation.
Maybe is there a method to send binary file to f***d postgresql server (I really don't like it, but my client is stubborn).

It's possible with python, but I don't want to mix harbour with python.]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by mol]]> 2025-09-12T14:25:47+00:00 2025-09-12T14:25:47+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71904#p71904 Of course, your function to encode file will be very useful!

Schema of my idea - encode value to base64 string - it will be 1.5 times bigger than source, but it can be transferred to a server without worries about UTF8 encoding, special chars etc.
After that, we can save our content decoding it with built-in postgres function.

Code: Select all

cContent := hb_Base64Encode( hb_memoread("place.jpg") )
cSQL := "INSERT INTO images (Zawartosc) VALUES (decode('" + cContent + "','base64' ) ) RETURNING Image_ID"
aTmp := pgSelectQuery(oServerMaster,cSQL, .t.)
if empty(aTmp)
	MsgDebug("Error!")
	return
endif

// retriving file from server
nId := aTmp[1,1]
	
cSQL := "SELECT encode(Zawartosc::ByteA, 'base64') FROM  images WHERE image_id = " + hb_ntos(nId)
aTmp := pgSelectQuery(oServerMaster,cSQL, .f.)
	
if !empty(aTmp)
	hb_memowrit('Odpowiedz.jpg', hb_Base64Decode(aTmp[1][1]))
	execute file 'odpowiedz.jpg'
endif

Hope it will help someone ;) ]]>
Of course, your function to encode file will be very useful!

Schema of my idea - encode value to base64 string - it will be 1.5 times bigger than source, but it can be transferred to a server without worries about UTF8 encoding, special chars etc.
After that, we can save our content decoding it with built-in postgres function.

Code: Select all

cContent := hb_Base64Encode( hb_memoread("place.jpg") )
cSQL := "INSERT INTO images (Zawartosc) VALUES (decode('" + cContent + "','base64' ) ) RETURNING Image_ID"
aTmp := pgSelectQuery(oServerMaster,cSQL, .t.)
if empty(aTmp)
	MsgDebug("Error!")
	return
endif

// retriving file from server
nId := aTmp[1,1]
	
cSQL := "SELECT encode(Zawartosc::ByteA, 'base64') FROM  images WHERE image_id = " + hb_ntos(nId)
aTmp := pgSelectQuery(oServerMaster,cSQL, .f.)
	
if !empty(aTmp)
	hb_memowrit('Odpowiedz.jpg', hb_Base64Decode(aTmp[1][1]))
	execute file 'odpowiedz.jpg'
endif

Hope it will help someone ;) ]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by srvet_claudio]]> 2025-09-13T02:01:13+00:00 2025-09-13T02:01:13+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71906#p71906 Have you tried saving the image directly as a BLOB data?
Like this:

CREATE TABLE Image (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
imageData LONGBLOB
);]]>
Have you tried saving the image directly as a BLOB data?
Like this:

CREATE TABLE Image (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
imageData LONGBLOB
);]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by mol]]> 2025-09-13T17:27:03+00:00 2025-09-13T17:27:03+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71908#p71908 <![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by serge_girard]]> 2025-09-13T17:29:53+00:00 2025-09-13T17:29:53+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71909#p71909 Looks good to me:

Code: Select all

cContent := hb_Base64Encode( hb_memoread("place.jpg") )
cSQL := "INSERT INTO images (Zawartosc) VALUES (decode('" + cContent + "','base64' ) ) RETURNING Image_ID"
aTmp := pgSelectQuery(oServerMaster,cSQL, .t.)
if empty(aTmp)
	MsgDebug("Error!")
	return
endif

// retriving file from server
nId := aTmp[1,1]
	
cSQL := "SELECT encode(Zawartosc::ByteA, 'base64') FROM  images WHERE image_id = " + hb_ntos(nId)
aTmp := pgSelectQuery(oServerMaster,cSQL, .f.)
	
if !empty(aTmp)
	hb_memowrit('Odpowiedz.jpg', hb_Base64Decode(aTmp[1][1]))
	execute file 'odpowiedz.jpg'
endif

]]>
Looks good to me:

Code: Select all

cContent := hb_Base64Encode( hb_memoread("place.jpg") )
cSQL := "INSERT INTO images (Zawartosc) VALUES (decode('" + cContent + "','base64' ) ) RETURNING Image_ID"
aTmp := pgSelectQuery(oServerMaster,cSQL, .t.)
if empty(aTmp)
	MsgDebug("Error!")
	return
endif

// retriving file from server
nId := aTmp[1,1]
	
cSQL := "SELECT encode(Zawartosc::ByteA, 'base64') FROM  images WHERE image_id = " + hb_ntos(nId)
aTmp := pgSelectQuery(oServerMaster,cSQL, .f.)
	
if !empty(aTmp)
	hb_memowrit('Odpowiedz.jpg', hb_Base64Decode(aTmp[1][1]))
	execute file 'odpowiedz.jpg'
endif

]]>
<![CDATA[HMG Samples :: Re: EASY.SQL.2025.09.01 (A lot of new stuff!) :: Reply by mol]]> 2025-09-14T08:52:19+00:00 2025-09-14T08:52:19+00:00 http://mail.hmgforum.com/viewtopic.php?f=9&t=7689&p=71910#p71910 <![CDATA[Others :: xBase Package :: Author msdn]]> 2025-09-02T16:28:49+00:00 2025-09-02T16:28:49+00:00 http://mail.hmgforum.com/viewtopic.php?f=11&t=7692&p=71884#p71884 Visit the website and see how to purchase.

https://harbourdeveloper.blogspot.com/

Thank you very much for your attention.]]>
Visit the website and see how to purchase.

https://harbourdeveloper.blogspot.com/

Thank you very much for your attention.]]>
<![CDATA[My HMG Projects :: xBase Package :: Author msdn]]> 2025-09-02T16:27:25+00:00 2025-09-02T16:27:25+00:00 http://mail.hmgforum.com/viewtopic.php?f=15&t=7691&p=71883#p71883 Visit the website and see how to purchase.

https://harbourdeveloper.blogspot.com/

Thank you very much for your attention.]]>
Visit the website and see how to purchase.

https://harbourdeveloper.blogspot.com/

Thank you very much for your attention.]]>
<![CDATA[My HMG Projects :: Codificador :: Author LOUIS]]> 2025-09-09T00:24:07+00:00 2025-09-09T00:24:07+00:00 http://mail.hmgforum.com/viewtopic.php?f=15&t=7697&p=71890#p71890
  • Hello friends of HMG

    I've been messing around a bit with the help of AI and managed to create a program that receives text directly
    from the keyboard, or it can also receive it from a copy and paste, and converts it to a "coded language" or perhaps
    you could call it "encrypted" :roll:

    It supports up to 60 lines of text (although it can be manipulated in prg).
    Perhaps this may seem trivial to some, but for me, as I'm not a Systems Engineer,
    but rather a self-taught programmer, I feel very happy. :mrgreen:

    I'm sharing the code with you because I've learned a lot from this Forum over the years,
    and I want to give back to you what I discover.

    The characters accepted for encoding are letters and numbers; everything else is preserved in its original form,
    such as "úñ#!+óÉ,;:Á-*/?%\, etc.

    Greetings to all.

    Louis

    P.S. - By default, it saves RECORDING_ENCODED.TXT and RECORDING_DECODED.TXT inside the working folder.
    • Svool uirvmwh lu SNT

      R'ev yvvm nvhhrmt zilfmw z yrg drgs gsv svok lu ZR zmw nzmztvw gl xivzgv z kiltizn gszg ivxvrevh gvcg wrivxgob
      uiln gsv pvbylziw, li rg xzm zohl ivxvrev rg uiln z xlkb zmw kzhgv, zmw xlmevigh rg gl z "xlwvw ozmtfztv" li kviszkh
      blf xlfow xzoo rg "vmxibkgvw" :roll:

      Rg hfkkligh fk gl 39 ormvh lu gvcg (zogslfts rg xzm yv nzmrkfozgvw rm kit).
      Kviszkh gsrh nzb hvvn girerzo gl hlnv, yfg uli nv, zh R'n mlg z Hbhgvnh Vmtrmvvi,
      yfg izgsvi z hvou-gzftsg kiltiznnvi, R uvvo evib szkkb. :mrgreen:

      R'n hszirmt gsv xlwv drgs blf yvxzfhv R'ev ovzimvw z olg uiln gsrh Ulifn levi gsv bvzih,
      zmw R dzmg gl trev yzxp gl blf dszg R wrhxlevi.

      Gsv xszizxgvih zxxvkgvw uli vmxlwrmt ziv ovggvih zmw mfnyvih; vevibgsrmt vohv rh kivhvievw rm rgh lirtrmzo ulin,
      hfxs zh "úñ#!+óÉ,;:Á-*/?%\, vgx.

      Tivvgrmth gl zoo.

      Olfrh

      K.H. - Yb wvuzfog, rg hzevh IVXLIWRMT_VMXLWVW.GCG zmw IVXLIWRMT_WVXLWVW.GCG rmhrwv gsv dliprmt ulowvi.
    • Hola amigos del HMG

      Estuve traveseando un poco con ayuda de la AI y logré hacer un programa que recibe un escrito
      directamente del teclado, o lo puede también recibir de un copia y pega, y lo traspasa a un
      "lenguaje codificado" o quizás pueda decirse "encriptado" :roll:

      Soporta hata 60 líneas de texto (aunque se lo puede manipular en el prg).
      Quizás para alguien pueda ser una trivialidad, pero para mí que no soy un Ing.de Sistemas,
      sino un programador autodidacta, me siento muy feliz. :mrgreen:

      Os comparto el código, porque de éste Forum he aprendido bastante, durante algunos años ya,
      y quiero devolveros lo que vaya descubriendo.

      Los caracteres que acepta para codificar son letras y números, todo lo demás se respeta su
      forma original, como "úñ#!+óÉ,;:Á-*/?%\ etc.

      Saludos a todos.

      Louis

      P.D.- Graba por default GRABADO_CODIFICADO.TXT y GRABADO_DECODIFICADO.TXT dentro de la carpeta
      de trabajo.
    • Sloz znrtlh wvo SNT

      Vhgfev gizevhvzmwl fm klxl xlm zbfwz wv oz ZR b oltié szxvi fm kiltiznz jfv ivxryv fm vhxirgl
      wrivxgznvmgv wvo gvxozwl, l ol kfvwv gznyrém ivxryri wv fm xlkrz b kvtz, b ol gizhkzhz z fm
      "ovmtfzqv xlwrurxzwl" l jfraáh kfvwz wvxrihv "vmxirkgzwl" :roll:

      Hlkligz szgz 39 oímvzh wv gvcgl (zfmjfv hv ol kfvwv nzmrkfozi vm vo kit).
      Jfraáh kziz zotfrvm kfvwz hvi fmz girerzorwzw, kvil kziz ní jfv ml hlb fm Rmt.wv Hrhgvnzh,
      hrml fm kiltiznzwli zfglwrwzxgz, nv hrvmgl nfb uvora. :mrgreen:

      Lh xlnkzigl vo xówrtl, klijfv wv éhgv Ulifn sv zkivmwrwl yzhgzmgv, wfizmgv zotfmlh zñlh bz,
      b jfrvil wveloevilh ol jfv ezbz wvhxfyirvmwl.

      Olh xzizxgvivh jfv zxvkgz kziz xlwrurxzi hlm ovgizh b múnvilh, glwl ol wvnáh hv ivhkvgz hf
      ulinz lirtrmzo, xlnl "úñ#!+óÉ,;:Á-*/?%\ vgx.

      Hzofwlh z glwlh.

      Olfrh

      K.W.- Tizyz kli wvuzfog TIZYZWL_XLWRURXZWL.GCG b TIZYZWL_WVXLWRURXZWL.GCG wvmgil wv oz xzikvgz
      wv gizyzql.

    Attachments

    CODIFICADOR.rar (0.7 KiB)
    CODICE_CONH.rar (1.65 KiB)

    CODICE.png (3.33 KiB)

    ]]>
  • Hello friends of HMG

    I've been messing around a bit with the help of AI and managed to create a program that receives text directly
    from the keyboard, or it can also receive it from a copy and paste, and converts it to a "coded language" or perhaps
    you could call it "encrypted" :roll:

    It supports up to 60 lines of text (although it can be manipulated in prg).
    Perhaps this may seem trivial to some, but for me, as I'm not a Systems Engineer,
    but rather a self-taught programmer, I feel very happy. :mrgreen:

    I'm sharing the code with you because I've learned a lot from this Forum over the years,
    and I want to give back to you what I discover.

    The characters accepted for encoding are letters and numbers; everything else is preserved in its original form,
    such as "úñ#!+óÉ,;:Á-*/?%\, etc.

    Greetings to all.

    Louis

    P.S. - By default, it saves RECORDING_ENCODED.TXT and RECORDING_DECODED.TXT inside the working folder.
    • Svool uirvmwh lu SNT

      R'ev yvvm nvhhrmt zilfmw z yrg drgs gsv svok lu ZR zmw nzmztvw gl xivzgv z kiltizn gszg ivxvrevh gvcg wrivxgob
      uiln gsv pvbylziw, li rg xzm zohl ivxvrev rg uiln z xlkb zmw kzhgv, zmw xlmevigh rg gl z "xlwvw ozmtfztv" li kviszkh
      blf xlfow xzoo rg "vmxibkgvw" :roll:

      Rg hfkkligh fk gl 39 ormvh lu gvcg (zogslfts rg xzm yv nzmrkfozgvw rm kit).
      Kviszkh gsrh nzb hvvn girerzo gl hlnv, yfg uli nv, zh R'n mlg z Hbhgvnh Vmtrmvvi,
      yfg izgsvi z hvou-gzftsg kiltiznnvi, R uvvo evib szkkb. :mrgreen:

      R'n hszirmt gsv xlwv drgs blf yvxzfhv R'ev ovzimvw z olg uiln gsrh Ulifn levi gsv bvzih,
      zmw R dzmg gl trev yzxp gl blf dszg R wrhxlevi.

      Gsv xszizxgvih zxxvkgvw uli vmxlwrmt ziv ovggvih zmw mfnyvih; vevibgsrmt vohv rh kivhvievw rm rgh lirtrmzo ulin,
      hfxs zh "úñ#!+óÉ,;:Á-*/?%\, vgx.

      Tivvgrmth gl zoo.

      Olfrh

      K.H. - Yb wvuzfog, rg hzevh IVXLIWRMT_VMXLWVW.GCG zmw IVXLIWRMT_WVXLWVW.GCG rmhrwv gsv dliprmt ulowvi.
    • Hola amigos del HMG

      Estuve traveseando un poco con ayuda de la AI y logré hacer un programa que recibe un escrito
      directamente del teclado, o lo puede también recibir de un copia y pega, y lo traspasa a un
      "lenguaje codificado" o quizás pueda decirse "encriptado" :roll:

      Soporta hata 60 líneas de texto (aunque se lo puede manipular en el prg).
      Quizás para alguien pueda ser una trivialidad, pero para mí que no soy un Ing.de Sistemas,
      sino un programador autodidacta, me siento muy feliz. :mrgreen:

      Os comparto el código, porque de éste Forum he aprendido bastante, durante algunos años ya,
      y quiero devolveros lo que vaya descubriendo.

      Los caracteres que acepta para codificar son letras y números, todo lo demás se respeta su
      forma original, como "úñ#!+óÉ,;:Á-*/?%\ etc.

      Saludos a todos.

      Louis

      P.D.- Graba por default GRABADO_CODIFICADO.TXT y GRABADO_DECODIFICADO.TXT dentro de la carpeta
      de trabajo.
    • Sloz znrtlh wvo SNT

      Vhgfev gizevhvzmwl fm klxl xlm zbfwz wv oz ZR b oltié szxvi fm kiltiznz jfv ivxryv fm vhxirgl
      wrivxgznvmgv wvo gvxozwl, l ol kfvwv gznyrém ivxryri wv fm xlkrz b kvtz, b ol gizhkzhz z fm
      "ovmtfzqv xlwrurxzwl" l jfraáh kfvwz wvxrihv "vmxirkgzwl" :roll:

      Hlkligz szgz 39 oímvzh wv gvcgl (zfmjfv hv ol kfvwv nzmrkfozi vm vo kit).
      Jfraáh kziz zotfrvm kfvwz hvi fmz girerzorwzw, kvil kziz ní jfv ml hlb fm Rmt.wv Hrhgvnzh,
      hrml fm kiltiznzwli zfglwrwzxgz, nv hrvmgl nfb uvora. :mrgreen:

      Lh xlnkzigl vo xówrtl, klijfv wv éhgv Ulifn sv zkivmwrwl yzhgzmgv, wfizmgv zotfmlh zñlh bz,
      b jfrvil wveloevilh ol jfv ezbz wvhxfyirvmwl.

      Olh xzizxgvivh jfv zxvkgz kziz xlwrurxzi hlm ovgizh b múnvilh, glwl ol wvnáh hv ivhkvgz hf
      ulinz lirtrmzo, xlnl "úñ#!+óÉ,;:Á-*/?%\ vgx.

      Hzofwlh z glwlh.

      Olfrh

      K.W.- Tizyz kli wvuzfog TIZYZWL_XLWRURXZWL.GCG b TIZYZWL_WVXLWRURXZWL.GCG wvmgil wv oz xzikvgz
      wv gizyzql.

    Attachments

    CODIFICADOR.rar (0.7 KiB)
    CODICE_CONH.rar (1.65 KiB)

    CODICE.png (3.33 KiB)

    ]]>
    <![CDATA[My HMG Projects :: 📢 Announcement: Exclusive Access to Private MiniGUI 25.09 Builds :: Author gfilatov]]> 2025-09-12T16:02:48+00:00 2025-09-12T16:02:48+00:00 http://mail.hmgforum.com/viewtopic.php?f=15&t=7699&p=71905#p71905
    We’re pleased to announce the release of exclusive Private MiniGUI 25.09 build packages, available only to our valued donors.

    The following packages are now available:

    🔹 MiniGUI 64-bit Package
    Includes:

    * Harbour MiniGUI Extended Edition 25.09 (PRO)
    * Harbour 3.2.0dev (r2509100708)
    * Harbour Make (hbmk2) 3.2.0dev (r2025-09-10 07:08)
    * gcc version 15.2.0 (MinGW-W64 x86_64-msvcrt-posix-seh, built by Brecht Sanders, r1)

    ---

    🔹 MiniGUI BCC 7.70 Package
    Includes:

    * Harbour MiniGUI Extended Edition 25.09 (PRO)
    * Harbour 3.2.0dev (r2509091755)
    * Harbour Make (hbmk2) 3.2.0dev (r2025-09-09 17:55)
    * Embarcadero C++ 7.70 for Win32
    © 1993–2023 Embarcadero Technologies, Inc.

    ---

    🔹 MiniGUI xHarbour Package
    Includes:

    * Harbour MiniGUI Extended Edition 25.09 (Standard)
    * xHarbour 1.3.2 Intl. (SimpLex) (Build 20250515)
    * Embarcadero C++ 7.70 for Win32
    © 1993–2023 Embarcadero Technologies, Inc.

    ---

    These builds are exclusively available to MiniGUI donors as a token of our gratitude for your continued support.]]>

    We’re pleased to announce the release of exclusive Private MiniGUI 25.09 build packages, available only to our valued donors.

    The following packages are now available:

    🔹 MiniGUI 64-bit Package
    Includes:

    * Harbour MiniGUI Extended Edition 25.09 (PRO)
    * Harbour 3.2.0dev (r2509100708)
    * Harbour Make (hbmk2) 3.2.0dev (r2025-09-10 07:08)
    * gcc version 15.2.0 (MinGW-W64 x86_64-msvcrt-posix-seh, built by Brecht Sanders, r1)

    ---

    🔹 MiniGUI BCC 7.70 Package
    Includes:

    * Harbour MiniGUI Extended Edition 25.09 (PRO)
    * Harbour 3.2.0dev (r2509091755)
    * Harbour Make (hbmk2) 3.2.0dev (r2025-09-09 17:55)
    * Embarcadero C++ 7.70 for Win32
    © 1993–2023 Embarcadero Technologies, Inc.

    ---

    🔹 MiniGUI xHarbour Package
    Includes:

    * Harbour MiniGUI Extended Edition 25.09 (Standard)
    * xHarbour 1.3.2 Intl. (SimpLex) (Build 20250515)
    * Embarcadero C++ 7.70 for Win32
    © 1993–2023 Embarcadero Technologies, Inc.

    ---

    These builds are exclusively available to MiniGUI donors as a token of our gratitude for your continued support.]]>
    <![CDATA[My HMG Projects :: Re: 📢 Announcement: Exclusive Access to Private MiniGUI 25.09 Builds :: Reply by serge_girard]]> 2025-09-13T06:06:01+00:00 2025-09-13T06:06:01+00:00 http://mail.hmgforum.com/viewtopic.php?f=15&t=7699&p=71907#p71907 <![CDATA[General Discussions :: xBase Package :: Author msdn]]> 2025-09-02T16:21:16+00:00 2025-09-02T16:21:16+00:00 http://mail.hmgforum.com/viewtopic.php?f=12&t=7690&p=71882#p71882 Visit the website and see how to purchase.

    https://harbourdeveloper.blogspot.com/

    Thank you very much for your attention.]]>
    Visit the website and see how to purchase.

    https://harbourdeveloper.blogspot.com/

    Thank you very much for your attention.]]>