Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Display in txtboxes and tableupdate() 1

Status
Not open for further replies.

sashaDG

Programmer
Jun 20, 2022
112
BY
Hi all. You help me a lot with FOKSPR, my respect to you! Next question:
The pageframe.page1 has an ADD button

Code:
SELECT main_dir
=CURSORSETPROP("Buffering", 3)
APPEND BLANK

ThisForm.Pageframe1.ActivePage = 2

In pageframe1.page2 i have empty(cause append blank) textBoxes whose source is maindir.colum.
I write to textBoxes and save, everything works well
Code:
WITH Thisform.pageframe1.page2
	.txtKpost.Value = ALLTRIM(main_dir.Kpost)
	.txtNaimp.Value = ALLTRIM(main_dir.Naimp)
	.txtNaim.Value = ALLTRIM(main_dir.Naim)
	.txtOdse.Value = ALLTRIM(main_dir.Odse)	
ENDWITH

=TABLEUPDATE()
=CURSORSETPROP("Buffering", 1)

ThisForm.Pageframe1.page1.Enabled = .T.
ThisForm.Pageframe1.ActivePage = 1
ThisForm.pageframe1.page1.Refresh

But in the pageframe1.page2 there is a button 'Add from another table' (DO FORM search)

By clicking the search.btnAdd, txtBoxes in the pageframe1.page2 are filled with data from the FORM search.
Code:
WITH NameMainForm.pageframe1.page2
	.txtKpost.Value = ALLTRIM(SortedData.Kpost)
	.txtNaimp.Value = ALLTRIM(SortedData.Naimp)
	.txtNaim.Value = ALLTRIM(SortedData.Naim)
	.txtOdse.Value = ALLTRIM(SortedData.Odse)
	.txtKol.Value = SortedData.Kol
	.txtCena.Value = SortedData.Cena
	.txtSumma.Value = SortedData.Summa		
ENDWITH
*!*	NameMainForm.PAGEFRAME1.PAge1.grdMain_dir.SetFocus
*!*	NameMainForm.PAGEFRAME1.PAge1.grdMain_dir.REFRESH
UsedBtn3Chose= .T.
ThisForm.Release
CLEAR EVENTS

At THIS moment[highlight #FCE94F] I don't need[/highlight] click BtnSave, because if I go to page1 to the main_grid, the record will already be filled. That is, it automatically makes a tablupdate.

I want to control the addition from the form search: after the btnAdd button, so that you have to click the BtnSave or Editbtn(there is record that I added and which must be filled in the txtBoxes). I think it's the assignment in the btnAdd.
 
Your question seems a bit buried, I actually don't know what exactly to answer.

But I see you set the VALUES of textboxes. This should only be done to fill in new or different values than come from the controlsource.
For TABLEUPDATE to save the data in the controls, the controls have to be set to the right controlsoruces. And that's a two-way connection from cursor to control and back and thus also into DBF or remote SQL Server backend via TABLEUPDATE.

If you just set a textbox.value to cursor.field, you establish a connection. Any edit/modification of the textbox value will not go back to cursor.field of the field that TABLEUPDATE eventually saves into the backend table.

You need to learn to use the CONTROLÖSOURCE, not the value.

And again I have to tell that TABLEUPDATE() is a function that NEEDS parameters, don't just do TABLEUPDATE, that a9 relies on the active workarea being the one you want to save, and b) only saves the current record. You use Buffering 1, which also is wrong, as it's no buffering at all. That doesn't only make TABLEUPDATE unnecessary, it even makes it wrong. But you will need TABLEUPDATE, it's no good idea to work unbuffered with an SQL Server backend. You usually will work in buffermode 5.

The value is what you display and modify within a control, whether controlsource is set or not, but only setting the value doesn't bind it two-ways to that field. And no matter whether you explicitly decide against buffering or not, using the controlsource is non-optional, it's a must-have. And when you set that, you don't need to set the value, because the controlsource does that. It's two-ways, the current value is set and modified values are stored back.

Chriss
 
I need that after adding from form search, the values ​​are displayed in txtBoxes ​​and I have the choice to cancel the record or BtnSave
Code:
	SELECT main_dir
	DELETE
	=TABLEREVERT()
 
I'm also finding your question a little difficult to understand. I hope that Chris has given you some useful information.

I'll just pick up one point. TABLEREVERT() does indeed cancel any changes made while the table was buffered. But there is no point in doing a DELETE immediately before the TABLEREVERT(). The effect of that is to cancel the deletion, which I assume is not what you want.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
To add to what Mike said about TABLEREVERT: It is the only function you need to revert one or all records, including to get back to the state an added record didn't exist. Reverting doesn't just mean to get back to the initial state of a record, if a record didn't exist at start of buffering, it also is removed again, so really no need to DELETE.

What you do with new records is append them, or, if you have different schemas, you have to APPEND BLANK and then fill in the fields with the correct mapping replace cursor.fieldX with othertable.fieldY where fieldY is not the same name but corresponds to what fieldX should store. You get these kind of non-identical table schemas easily, if data is from different databases/vendors. If you design both source and target table it's a good idea to have same field names for same type of data.

You could then also think about why you actually have to copy from one to another table and whether your table design is correct, as most of the time you'd just set a foreign key to reference the same data instead of actually copying it over.

Aside of all that, notice I talked about copying data from source to target table. The CONTROLSOURCE (again) is what transports this into the control and display, not your code.

Chriss
 
One more thing.

As you said:
sashaDG said:
I [highlight #FCE94F]don't need[/highlight] click BtnSave, because if I go to page1 to the main_grid, the record will already be filled. That is, it automatically makes a tablupdate.
Well, you're likely wrong here as i don't know about your controlsource settings. Setting the value only displays what you set there, it's not yet saved. Controls even buffer if you don't have buffermode, as what you have in the value only is stored back to the controlsource when control.valid allows it, returns .T., and you can't just call valid, it has to happen as event, and that's when a control is losing focus, when you tab away or change focus by ENTER key.

If you set the value and a control hasn't even got focus, you even are two steps away from setting the controlsource.

So if you want to copy data between source and target tables, then do exactly that, controls are only the display and user interface, always secondary and not primary to use programmatically.

Especially since you also say
sasha DG said:
I have the choice to cancel the record or BtnSave
That's what you only can do with active buffering (3 or 5, not 1) and then tablerevert cancels changes, tableupdate(2,.t.,....) (look for the parameterization, please, there are many possibilities which each can be right and you have to know what you want to save, current record, all changes, whatever and what information you want to receive about the change, success overall, per record using the errorarray).

REVERT can only work on BUFFERED changes, it will not turn back saved changes, that should also be clear. You a) didn't yet activate buffering, as 1 isn't a buffermode but turns it off and so you cant cancel things you already did. Then you actually need DELETE, if it's only about deleting a new record, but think of an update you did, The update really writes new values into the existing record and the old values are gone, if you didn't memorize them, there is no simple rollback command to the old state, even though SQL Server keeps a transaction log. It would become an administrative task to go back to an older state in the Server transaction log, a task part of a restore operation.

Likewise, if you start a transaction, you can rollback, but only up to the position where the transaction started. Using no buffering you waive to have such a rollback state, every change is final and already committed and the only way back is a complicated administrative tasks and not an operation you would do in an application on each client. Also, because that transaction log isn't per user it's about all of the database, so you could roll back other users changes just because you made a mistake.

That's also why the interface should always buffer, then you actually have something in your hand, only concerning that one client/user and his changes, not the whole database. There's the pro of buffering over transactions. And just to round this off, the subtle differences are also a reason to combine both things and not use one or the other, they have different means.

Chriss
 
said:
If you just set a textbox.value to cursor.field, you establish a connection. Any edit/modification of the textbox value will not go back to cursor.field of the field that TABLEUPDATE eventually saves into the backend table.
I didn't understand this point

said:
You could then also think about why you actually have to copy from one to another table and whether your table design is correct, as most of the time you'd just set a foreign key to reference the same data instead of actually copying it over.
I definitely don't need it

I still don't understand: why fields are saved without tablupdate (cause to values)?

said:
That's what you only can do with active buffering (3 or 5, not 1) and then tablerevert cancels changes, tableupdate(2,.t.,....) (look for the parameterization, please, there are many possibilities which each can be right and you have to know what you want to save, current record, all changes, whatever and what information you want to receive about the change, success overall, per record using the errorarray).
i have buffering 3 in ADDBTN

said:
REVERT can only work on BUFFERED changes, it will not turn back saved changes, that should also be clear. You a) didn't yet activate buffering, as 1 isn't a buffermode but turns it off and so you cant cancel things you already did. Then you actually need DELETE, if it's only about deleting a new record, but think of an update you did, The update really writes new values into the existing record and the old values are gone, if you didn't memorize them, there is no simple rollback command to the old state, even though SQL Server keeps a transaction log. It would become an administrative task to go back to an older state in the Server transaction log, a task part of a restore operation.
Im need BUFFERED changes, not rollback, but its buffered changes immediately moved to the grid without tableupdate
 
I still don't understand: why fields are saved without tablupdate

This is because you have the buffer mode set to 3, which means that you are using row buffering. With row buffering in force, there will be an implict table update (that is, data will be written to the table) whenever the record point moves off the record that has been edited. This is probably what is happening here.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Chris Miller, your thoughts about that are losing focus.
Chris Miller said:
Well, you're likely wrong here as i don't know about your controlsource settings. Setting the value only displays what you set there, it's not yet saved. Controls even buffer if you don't have buffermode, as what you have in the value only is stored back to the controlsource when control.valid allows it, returns .T., and you can't just call valid, it has to happen as event, and that's when a control is losing focus, when you tab away or change focus by ENTER key.

Forced me after clicking the add button to insert "getting focus"
Code:
ThisForm.pageframe1.page2.txtKpost.Enabled = .T.
ThisForm.pageframe1.page2.txtNaimp.Enabled = .T.
...
Its WORK!!! Thank u
 
Enabling textboxes doesn't set focus to them. You still don't say anything about your controlsources and they are the most important to set to display and save what you display or modify (or SET).

Chriss
 
I have table main_dir.
txtKpost, txtNaimp ... have always controlSource main_dir.Kpost, main_dir.Naim
 
Then all you need to change is main_dir fields, not txtKpost or txtNaimp values.

Besides that, if you APPEND data and then DELETE it you do about the same as tablerevert does for this special case, but you still have the new record marked deleted. If you start actual buffering (mode 3,5) and then append a record and TABLEREVERT you get back to the state that record did not exist yet, it doesn't occupy a record it's not just marked deleted, it's actually gone as if it was never appended. And that's an advantage you're missing out if you don't do buffering correctly.

Chriss
 
Сhris, what you listed: APPEND BLANK,CURSORSETPROP("Buffering", 3), TABLEREVERT . I used in code

Chris said:
Then all you need to change is main_dir fields, not txtKpost or txtNaimp values.
Can you show me example, please?
 
Sasha,

You did post this code, didn't you?
Code:
ITH NameMainForm.pageframe1.page2
	.txtKpost.Value = ALLTRIM(SortedData.Kpost)
	.txtNaimp.Value = ALLTRIM(SortedData.Naimp)
	.txtNaim.Value = ALLTRIM(SortedData.Naim)
	.txtOdse.Value = ALLTRIM(SortedData.Odse)
	.txtKol.Value = SortedData.Kol
	.txtCena.Value = SortedData.Cena
	.txtSumma.Value = SortedData.Summa		
ENDWITH

You have buffered the table with data you finally want to save (tableupdate) or cancel (tablerevert), then copy SrtedData To main_dir and not to controls bound to main_dir. The controls then follow, i.e. they display the changed (and buffered) main_dir data (which then still can be reverted or submitted). That's the way to go about this, what you do is in reverse.

The frontend is there to react to what happens in the data on one side, and it's there as user interface, but not as program interface. So instead of all that tetbox.value setting you do a REPLACE field1 With newvalue1, field2 with newvalue etc. And since the controls are bound by controlsource they will show that.

It's not just more appropriate you don't get through any hassles of control values not getting back to the controlsource as you didn't yet fully cycle through the events of valid triggered by lsotfocus.

Chriss
 
Now it became clear to me. First of all, I need to understand how to insert from Sorted directly into the main_dir. When I get something, I'll post.
 
Well, the most direct way is using INSERT-SQL. Or APPEND BLANK plus a REPLACE.
There's also the "stoneage method" of scatter and gather.

It doesn't matter how you do it, the effect on the buffer is the same, and as you go direct to your target you avoid any side effects controls have on hindering the value to geet to the controlsource directly or not.

The only thing that should be necessary to get the form display updating is a thisform.refresh in this case, the most general way to refresh the form to show all current countrolsource data (or recordsource in case of a grid).

Chriss
 
Chris, you helped me a lot. I did it with a REPLACE and now everything works
Code:
REPLACE Kpost WITH ALLTRIM(SortedData.Kpost);
		Naimp WITH ALLTRIM(SortedData.Naimp);
		Naim  WITH ALLTRIM(SortedData.Naim);
		Odse  WITH ALLTRIM(SortedData.Odse);
		Kol   WITH SortedData.Kol;
		Cena  WITH SortedData.Cena;
		Summa WITH SortedData.Summa;
IN main_dir
 
REPLACE Kpost WITH ALLTRIM(SortedData.Kpost)

I haven't been closely following this thread, so apologies if this has already been addressed, but I was wondering why you are doing ALLTRIM() in the REPLACE.

It seems to me that, if the source data is wider than the target field, any extra spaces will be truncated. If the target field is wider than the source, it will be padded with spaces. Either way, the ALLTRIM() appears to be redundant.

This is not a big point. I am only asking out of curiosity.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I have a search function and when I fill in the data without ALLTRIM, records with spaces at the beginning are not included in the search.
 
Yes, I understand the reason for doing that with a search. But here you are doing a REPLACE.

Then again, I can see that if there are spaces at the start of the source, then you would probably want to get rid of them.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top