Just sharing a little information. I wasn't aware of MVD's native ability to hide and move columns in a tablegrid so easily. The following link shows a short video showing how this is easily done by the end user.

To do this, in the tablegrid properties, options, set the properties to the following status:
- goCanHideColumn = true
- goDisableColumnMoving = false


https://www.youtube.com/watch?v=smervFM_XHc

2

(9 replies, posted in Talks about all)

Mathias, thanks for suggesting applications that make it easier to use MVD. I already use SQL Studio, which is very good.

I also use the freeware AutoZipper v1.0.exe. To edit an MVD program, I create a project (Container) with Autozipper and include the following files: forms.xml, myapp.vdb, settings.ini, tables.ini, script.pas, sqlite.db and the "Report" folder. I select the option "run external file after completion" and enter the name of the file myapp.vdb. It creates a file with the file extension arq.zipper. When I run it, it makes a compressed backup of the files I included and at the end it edits myapp.vdb.

3

(9 replies, posted in General)

k245 wrote:

You may be interested in the technology of dynamic interface, which is created according to the description of the data structure. On the editing form, not only the correct taborder is set, but the elements themselves are automatically distributed on the form depending on its size, which the user can change during the program operation.
https://k245.ru/en/mvdb-en/dynamic-interface.html


Hello K245! I saw the link you sent, but I couldn't download Data Keeper, but I appreciate your feedback.

4

(9 replies, posted in General)

sparrow wrote:

I optimized the procedure a little to get rid of the loop within a loop.

Very good! Tankyou.

5

(9 replies, posted in General)

sparrow wrote:

A bit of a strange request. I'll describe a little how TabOrder works.

The components on the form that can receive focus are numbered starting from 0 and ending with the number of the last component, let's say 12. Changing TabOrder in the editor causes renumbering of other components on the form, but within 12 (the number of components on the form) in our case. This works for components that are simply PLACED ON THE FORM. The same procedure at RunTime of the program. It is impossible to assign other numbers and other ranges.
Let's assume that we are creating a panel on the form. We will place two more input fields on the panel. As a result, the panel will receive TabOrder = 13 and the new Edit will receive numbers 0 and 1, respectively. And so on. )))
Here is an example for the simplest case of placing Edit, Combo and Memo on the form. Sorting by coordinates is used. From left to right, from top to bottom.
When using Panels, Groups, etc., the complexity of use is significantly more complicated. Also, in the example I did not include Buttons in the distribution of numbers. How to determine TabOrder for them??? In my opinion, it’s still easier to set the numbering yourself at the final stage of designing your application. )

Hi Sparrow! Perfect! I had a hard time explaining what I wanted, but you completely solved my problem. Thank you very much!

6

(9 replies, posted in General)

sparrow wrote:

HI Roberto



... automatically assign the taborder number to the fields of a form, whenever the position of some of them was changed ...


How is that ?

Hi Sparrow, how are you? I may have misworded the words. Let me give you an example. I have 3 fields in a form, whose filling order when I press tab (taborder property) is 1,2,3. If I put field 2 in place of 1 and do not change the taborder property of each field, when I fill in the first field and press tab, the cursor will go to the field at the end of the form!!! So, I thought: if there was a routine that automatically changed the filling order every time I moved a field in the form, it would be great!

7

(9 replies, posted in General)

Hello everyone! I searched the forum for a script that would automatically assign the taborder number to the fields of a form, whenever the position of some of them was changed, and I couldn't find it. Could anyone help?

8

(18 replies, posted in General)

sparrow wrote:

Hi Roberto


Something like this. The solution is of course like entering through the "back door"), but it works in 5.6 too.
Extra hidden RichEdit component on the form.
It is better to use the solution above, of course, but you have no choice.


Hi Sparrow, it worked!!! Thank you very much.

9

(18 replies, posted in General)

Hello everyone! I downloaded the examples posted here, but they didn't work on my version of MVD. Is it possible to adapt the "paste into dbimage JPG" to MVD 5.6?

P.S.: Does anyone know how to configure the forum to receive an email notifying me that there is a new message posted in a topic I opened?

sparrow wrote:

Hi Roberto


I tried to understand your application and decided to rework the example. I only worked on the repetitions. I think this will be clearer for you.

Hi Sparrow, sorry for the delay in responding. I was testing the changes you made to the script. Everything worked. I added a combobox for day and another for year, eliminating the checkboxes. I eliminated some fields that were not being used. I took the opportunity to include the filter for days of the week in the main SQL statement. Thanks again.

P.S. 09-10-24 (hora_fim added): application's core Sqlite instructions. Adjusted and now working fully as expected.

  Rec_Id := SQLExecute
  (
  ' SELECT id FROM reminder '
  +' WHERE MsgPopup = 1 '
  +' AND '
  +'     CASE WHEN rem_datetime IS NULL THEN '
  +'          ('
  +'          case when duedate is null then '
  +'               date(dateini) <= date("now", "localtime") '
  +'               AND '
  +'               date(dateini)||strftime(" %H:%M", datetime) <= date("now")||strftime(" %H:%M", "now", "localtime")'
  +'               AND '
  +'               case when hora_fim is not null then '
  +'                    date("now")||strftime(" %H:%M", hora_fim) >= date("now")||strftime(" %H:%M", "now", "localtime") else 1=1 end '
  +'          else '
  +'               date(duedate) <= date("now", "localtime") '
  +'               AND '
  +'               date(duedate)||strftime(" %H:%M", datetime) <= date("now")||strftime("%H:%M", "now", "localtime")'
  +'               AND '
  +'               case when hora_fim is not null then '
  +'                    date(duedate)||strftime(" %H:%M", hora_fim) >= date("now")||strftime(" %H:%M", "now", "localtime") else 1=1 end'
  +'          end '
  +'          ) '
  +'     ELSE '
  +'          datetime(rem_datetime) <= datetime("now", "localtime") '
  +'     END '
  +'     AND '
  +'     (  '
  +'     (dia_seg = 1 AND strftime("%w", "now","localtime") = "1") '
  +'     OR (dia_ter = 1 AND strftime("%w", "now","localtime") = "2") '
  +'     OR (dia_qua = 1 AND strftime("%w", "now","localtime") = "3") '
  +'     OR (dia_qui = 1 AND strftime("%w", "now","localtime") = "4") '
  +'     OR (dia_sex = 1 AND strftime("%w", "now","localtime") = "5") '
  +'     OR (dia_sab = 1 AND strftime("%w", "now","localtime") = "6") '
  +'     OR (dia_dom = 1 AND strftime("%w", "now","localtime") = "0") '
  +'     )'
  );


  If Rec_Id > '0' then
  Begin
      SQLexecute(
       ' UPDATE reminder '
      +' SET rem_datetime = '
      +'    datetime(max(date("now", "localtime")||" "||strftime("%H:%M:%S",datetime),datetime("now", "localtime")), '
      +'        cod_minutos||" minutes",'
      +'          cod_horas||" hours")'
      +' WHERE '
      +'    MsgPopup = 1 '
      +'    and (cod_minutos > 0 '
      +'         or cod_horas > 0 ) '
      +'    and id = '+Rec_Id);

      SQLexecute(
       ' UPDATE reminder '
      +' SET rem_datetime = '
      +'    datetime(date("now", "localtime")||" "||strftime("%H:%M:%S",datetime), '
      +'           cod_dias||" days",'
      +' ( cod_semanas * 7)||" days",'
      +'          cod_meses||" months",'
      +'           cod_anos||" years")'
      +' WHERE '
      +'    MsgPopup = 1 '
      +'    and (cod_dias > 0 '
      +'         or cod_semanas > 0 '
      +'         or cod_meses > 0 '
      +'         or cod_anos > 0 )'
      +'    and id = '+Rec_Id);
sparrow wrote:

Hi Roberto


Changed the solution, minutes as an example.
Tried to describe in the script.
The combo box is filled with minutes with ID.
ID is used when writing to the table as minutes.
The query checks the Date, TimeDate and vcto_hora fields.
If vcto_hora IS NULL the condition is checked by the TimeDate field otherwise vcto_hora.
After triggering, the vcto_hora field is changed by the repetition value and then triggers by this field.

In the future, I would convert the "vcto_hora" field to DateTime and collect the value for this field (strftime("%F %T", "now","localtime","'1 hours'","15 minutes", ...). Now only minutes.


P.S.  Sorry, I left an unnecessary Memo on the frmRemider form

Hi Sparrow, thank you very much. I see that it is working. I will take a look at the code to understand and learn what you did, to follow your suggestions and then try to finalize the other repetition options of frmReminder. Cheers.

sparrow wrote:

Hi Derek, Roberto


Extended version in rar


Hi Sparrow, this latest version of Nota bene is good. I tried to implement the repetition of times in the attached project but I couldn't. In the frmRemider form I put the desired repetition options. I would greatly appreciate it if you could indicate how you would repeat the time (datetime) in minutes (combobox cbo_minuto). Thanks

Hi Sparrow, as I said before, in Brazil we use the expression "show de bola" when we are surprised by something that turned out really well. Congratulations on the innovation!!

PS.: When I try to unzip the Windows 11 zip file, I get an error when unzipping the forms.xml file. I had to unzip it using Winrar, which worked.

Hi Sparrow, I tested the code below that you suggested and it worked very well!

I really liked the "notabene" project, sent by Derek. I already use the Eisenhower Matrix, which he posted. I made some adaptations to my needs and it has been very useful for organizing my tasks.


I don't have the knowledge and experience that you two have with MVD, but I intend to include the option of repeating tasks by minutes, hours, days, months or years in the ReminderTSA2_Revised project, which I found on the forum (attached).

Thanks again!

P.S.: The attached project used a messagebox to display the reminder when the date and time were reached. I replaced it with a form (frmMSG) so that the script suggested above by Sparrow would work.

tmpFormStyle : variant;
begin
  tmpFormStyle := Form1.FormStyle;
  Form1.FormStyle := fsStayOnTop;
  Application.restore;
  Form1.FormStyle := tmpFormStyle;

Sparrow and Derek, thank you very much! I will test it and post the results here.

In the projects published here on the forum, for task control or reminders with alarms, which are triggered at a certain time, I did not find the possibility of the alarm message being displayed when the application is hidden (Ctrl-D on Windows) or minimized. I tried "Form1.show" and "form1.windostate := wsNormal", but it did not work. Can anyone help?

P.S.: MVD 5.6

sparrow wrote:

Hi Roberto

I can't say that previous versions contained errors. Initially, all your problems were the "Ã" character in the CSV file.
When using TStringList, processing this character caused a failure and incorrect further work with the database.
What you considered a solution was a temporary solution until this or another similar character appeared again.
In the latest version, you used a different import solution. One of several possible ones. Import solutions based
on working with EXCEL are also possible. Of course, if you use this program.
In any case, I congratulate you on finding a solution. The "higher mind" is no better than your head.

thanks for the feedback

The import procedure I used presented some errors. I replaced it with another one created by Dmitri himself, specifically for importing CSV files (link below). Below is the corrected project.

The CSV file must have delimiters and periods in values with decimals, without column titles, as per the following example:



"ANHEMBI",16054542.98,0,0,5943,27.55
"BARUERI",1113402.53,0,0,486,2.25
"CASA VERDE",3379641.23,0,0,2918,13.53
"IBITIRA",3482791.97,0,0,2931,13.59
"INTERLAGOS",3634897.27,0,0,2766,12.82
"MARAJUARA",6232411.02,0,0,4304,19.95
"PORTA A PORTA",660044.78,0,0,354,1.64
"SÃO MATEUS",2736725.14,0,0,1869,8.66



https://myvisualdatabase.com/forum/sear … =435433873

Here is the project completed and working...still missing the printing

It imports delimited text (CSV) and generates charts from the imported data. I searched the internet via ChatGPT about the functions available to change the appearance of TeeChart charts (MVD 5.6) and included a button on each chart to do this customization.

20

(8 replies, posted in General)

k245 wrote:
sparrow wrote:

Procedures and functions, referred to collectively as routines, are self-contained statement blocks that can be called from different locations in a program. A function is a routine that returns a value when it executes. A procedure is a routine that does not return a value.

Let's change the code a little so that there is no cognitive dissonance. )) The function will return true if the field is added, and false if the field already exists.

Function Add_newfield(tabela,novo_campo,tipo,e_default,dado: string):boolean;
var
  ColResults: TDataset;
begin
  Result := True;
  SqlQuery('pragma table_info(['+tabela+']) ',ColResults);
  while not ColResults.Eof do
  begin
    if UpperCase( ColResults.FieldByName('name').asString ) = UpperCase( novo_campo ) then
    begin
      Result := False;
      Break;
    end;
    ColResults.Next;
  End;
  ColResults.Free;
  If Result then
  Begin
     SqlExecute('ALTER Table ['+tabela+'] ADD COLUMN ['+novo_campo+'] '+tipo+' '+E_DEFAULT+' '+dado+' ');
     if length(trim(dado)) > 0 then
         sqlexecute('UPDATE ['+tabela+'] SET  ['+novo_campo+'] ='+dado+' ');
  End;
end;

Sparrow and K245, tankyou.

sparrow wrote:

Hi Roberto


We kindly ask that in order to understand your problem, please indicate in the future exactly what errors occur.
When testing your program on my computer, you may get errors:
"Could not convert variant of type (UnicodeString) ..."
"Is not valid integer value..."
"Error message: no such column"

Hi Sparrow, you are right. Thanks for the guidance. When the project is complete, I will upload it again.

Problem solved! I replaced the line of code - CODE 1 with the line of code (CODE 2)


CODE 1:

                    SQLExecute('INSERT INTO '+TableName+' ('+Fields+') VALUES ('+sValues+')');

CODE 2;

                       instr_sql := '';
                       instr_sql := 'INSERT INTO ';
                       instr_sql := instr_sql + TableName;
                       instr_sql := instr_sql + ' ('+ Fields     + ') VALUES ';
                       instr_sql := instr_sql + ' (' + sValues + ')';
                       SQLExecute(instr_sql);

Hey guys! Here is a project I downloaded from the forum and I am adapting it to my needs. I have a tool called Visual Kit 5 v8, developed with Visual Foxpro which, although it is
old, has the advantage of building the entire application from just the "drawing" of the screens. The problem is that it uses MS's MSgraph.exe to generate graphs but, because it is old, this no longer works on Windows 11. Therefore, the objective is to use the attached project to generate graphs from data exported by Visual Kit to a CSV file. The MVD application (5.6) would load this data from the CSV file into a table and generate the graphs. The problem is that the import routine, which I also got here on the forum, works fine if the first column of the CSV is numeric. When the type is string, the process is interrupted by an error message.
I still plan to include printing and other customizations. In addition to using it with Visual KIt 5, I am thinking about the possibility of using it in applications whose development languages also depend on MSGraph.exe, to generate graphs. I appreciate any help that can be given.

CSV:

2007;15049861,72;0;0;6385;28,00
2008;2606270,58;0;0;2283;10,01
2009;3901885,82;0;0;3742;16,41
2010;3355533,20;0;0;3002;13,17
2011;6691013,64;0;0;4736;20,77
2012;517515,33;0;0;415;1,82
2013;2745497,70;0;0;2239;9,82

24

(8 replies, posted in General)

v_pozidis wrote:

Yes now it's clear. Thank's again

I converted the procedure from the project attached to this topic into a function, as follows:

Function Add_newfield(tabela,novo_campo,tipo,e_default,dado: string):nil;
var
  ColResults: TDataset;
  FieldExists: Boolean;
begin
    SqlQuery('pragma table_info(['+tabela+']) ',ColResults);
    while not ColResults.Eof do
       begin
          if UpperCase( ColResults.FieldByName('name').asString ) = UpperCase( novo_campo ) then
              FieldExists := True;
          ColResults.Next;
       End;
    ColResults.Free;

    If FieldExists = False then
    Begin
       SqlExecute('ALTER Table ['+tabela+'] ADD COLUMN ['+novo_campo+'] '+tipo+' '+E_DEFAULT+' '+dado+' ');
       if length(trim(dado)) > 0 then
           sqlexecute('UPDATE ['+tabela+'] SET  ['+novo_campo+'] ='+dado+' ');
    End;
end;

procedure Form1_OnShow (Sender: TObject; Action: string);
begin

//***************** CRIAR CAMPO NO SQLITE.DB ************************
    //  TEXT - INTEGER - REAL - BOOLEAN - CURRENCY -DATE/TIME - DATE - TIME - IMAGE
    //  Add_newfield(TABELA,NOVO_CAMPO,TIPO,E_DEFAULT,DADO);
    Add_newfield('tasks','favorito','BOOLEAN','DEFAULT','0');
    Add_newfield('tasks','dias_faltam','INTEGER','DEFAULT','0');
    Add_newfield('tasks','dias_adiar','INTEGER','DEFAULT','0');
    Add_newfield('tasks','link_recno','INTEGER','','');

//***************** CRIAR CAMPO NO SQLITE.DB ************************

end;

25

(8 replies, posted in General)

derek wrote:

Hi Roberto, Sparrow,
I've had no problems downloading and unzipping it.
But what I've done is re-zip Sparrow's program using different compression software - maybe you'll be able to unzip it now?
Derek.

Hi Derek, thank you very much for your prompt service and support. Hugs.