OpenOffice.org Forum at OOoForum.orgThe OpenOffice.org Forum
 
 [Home]   [FAQ]   [Search]   [Memberlist]   [Usergroups]   [Register
 [Profile]   [Log in to check your private messages]   [Log in

setString() Bug

 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Base
View previous topic :: View next topic  
Author Message
ch_ta
General User
General User


Joined: 05 Jan 2009
Posts: 8

PostPosted: Sun Jan 11, 2009 10:04 pm    Post subject: setString() Bug Reply with quote

Hello all, I'm still working on my project database and discovered something interesting. An additional function I desired to add to my database was to pass a string from a textfield in a form to another form's textfield, that is opened by the user.

I coded the function as an addition to the typical open form subroutine and discovered that if I did not have a message box present in my code then the textfield in the opened form would not show the text from the original textfield.

Here is the code:

Code:

Sub open_pass (Event as Object)
   Dim fm as Object       'form
   Dim fmd as Object      'form document
   Dim fmc as Object      'form collection
   Dim dbf As Object      'database form
   Dim nfmd as Object      'new form document
   Dim args(2) as New com.sun.star.beans.PropertyValue
   
   Dim fmM as Object      '"main" form
   Dim fmS as Object      '"sub" form
   Dim valMS as String      'text from "main" textfield
   
   fm = Event.Source.Model.Parent
   fmc = fm.Parent
   fmd = fmc.Parent 
   dbf = fmd.Parent

   args(0).Name = "ActiveConnection"
   args(0).Value = fm.ActiveConnection
   args(1).Name = "OpenMode"
   args(1).Value = "open"
   nfmd = dbf.FormDocuments.loadComponentFromURL("red_blue","_blank",0,Args())
   
   'Retrieve "main" form
   fmM = dbf.FormDocuments.getByName("red")
   fmM = fmM.Component.DrawPage.Forms.getByName("red_form")
   
   'Retrieve "sub" form
   fmS = dbf.FormDocuments.getByName("red_blue")
   fmS = fmS.Component.DrawPage.Forms.getByName("red_blue_form")
   
   'Get text in "main" textfield
   valMS = fmM.getByName("hotness").Text
   
   'Include a msgbox as a bug work around;
   'without a delay the "sub" form's textfield does not update
   MsgBox "Please continue..."
   
   'Place text into "sub" textfield
   fmS.getByName("hotness").setString(valMS)   
   
End Sub


If I comment the message box out then the text does not appear in the opened form. Any thoughts?

Note: I'm running OpenOffice 2.4.2
Back to top
View user's profile Send private message
RPG
Super User
Super User


Joined: 24 Apr 2008
Posts: 2697
Location: Apeldoorn, Netherland

PostPosted: Mon Jan 12, 2009 2:56 am    Post subject: Reply with quote

Hello

I do assume that the problem is in this line
Code:
fmS.getByName("hotness").setString(valMS)


It is not clear to me if you want only have a line in a textbox or it also must go to the table. So I give two lines of code

Code:
veld1.string="aap,noot,mies" ' for text box
veld1.boundfield.updatestring("peren in het veld") ' for text box and database


I think you have to change it in

Code:
fmS.getByName("hotness").string="aap,noot,mies"
fmS.getByName("hotness").boundfield.updatestring("peren in het veld")



I hope this helps you
Romke
Back to top
View user's profile Send private message
Voobase
OOo Advocate
OOo Advocate


Joined: 21 Nov 2007
Posts: 400
Location: Australia

PostPosted: Mon Jan 12, 2009 4:24 am    Post subject: Reply with quote

Hi Ch_ta,

I am wondering if you are having problems because of a "timing" issue. I notice that you open your form just prior to trying to copy something across to it. It might be that your subform has not finished loading, but you have already tried to copy text into one of its fields.

Have a look at this post where Romke and I have a bit of a discussion about these sort if timing issues.... http://www.oooforum.org/forum/viewtopic.phtml?t=77391
These sorts of problems seem to lead to a lot of mucking around and sometimes you think you have it nailed, but then you try your db out on a different computer and it fails again. I haven't found the "proper" way to deal with timing issues yet. Maybe there is something i'm missing.

In the thread I detail a couple of work arounds. Either you can use error handlers (if it is throwing errors) or a loop with a test to see when the subform is fully loaded or a combination of the two. The first of the three little macros in that thread seem's to be the one which worked best for me. It relies on checking a couple of the properties of the subform off against each other. When they agree it seems to indicate that the subform has finished loading. I should mention that the sub, as written, only works for me because I am making my subform go to the last record after the form loads (by doing a oSubform.last in a sub driven off the "when loading" event of subform). It might however give you some ideas for what you may need to do. If you find a neat, easy solution please share it!!


Cheers

Voo
Back to top
View user's profile Send private message
ch_ta
General User
General User


Joined: 05 Jan 2009
Posts: 8

PostPosted: Thu Jan 15, 2009 3:11 pm    Post subject: Reply with quote

Voo and Romke,

Just recently, I finished developing a test database (which informs my design for my project database) which involves a clean solution for passing a string. This springs from my effort to create a grid control that would display specific assignments for a given record.

Essentially, what I was developing in my test database was three tables that has a many to many relationship involved. One table is called "red" and has the fields "red_id" and "hot". Another table is called "blue" and has the fields "blue_id" and "cool". The many to many relationship involves the fields "hot" and "cool". There are many "hot" entries (i.e. projects) and many "cool" entries (i.e. staff) that are related to each other. The last table is called "red_blue" that has the fields "red_blue_id", "red_id" and "blue_id" (red_id and blue_id act as foreign keys). [Note: red and blue were selected as abstractions for my actual project database.]

I created three forms for each separate table.

The red form is where one can enter "hot" entries and open another form for the "red_blue" form. I created a macro that I attached to the open form button and it is the one that pulls the "hot" entry and "red_id" into the "red_blue" form. I pull the "red_id" into the "red_blue" form via database access methods. I place the "red_id" value into a corresponding formatted text field. The "hot" entry is placed into a formatted text field via a parametized query.

Macro attached to the open "red_blue" form button:

Code:

Sub open_pass (Event as Object)
   Dim fm as Object       'form
   Dim fmd as Object      'form document
   Dim fmc as Object      'form collection
   Dim dbf As Object      'database forms
   Dim nfmd as Object      'new form document
   Dim args(2) as New com.sun.star.beans.PropertyValue
   
   Dim fmM as Object      '"main" form
   Dim fmMPtr as Object   '"main" form pointer
   Dim fmS as Object      '"sub" form
   Dim valMS as String      'text from "main" textfield
   Dim valMI as Integer   'index
   Dim row as Integer      'row number
   
   fm = Event.Source.Model.Parent
   fmc = fm.Parent
   fmd = fmc.Parent 
   dbf = fmd.Parent

   args(0).Name = "ActiveConnection"
   args(0).Value = fm.ActiveConnection
   args(1).Name = "OpenMode"
   args(1).Value = "open"
   nfmd = dbf.FormDocuments.loadComponentFromURL("red_blue","_blank",0,Args())
   
   'Retrieve "main" form
   fmM = dbf.FormDocuments.getByName("red")
   fmM = fmM.Component.DrawPage.Forms.getByName("red_form")
   
   'Retrieve "sub" form
   fmS = dbf.FormDocuments.getByName("red_blue")
   fmS = fmS.Component.DrawPage.Forms.getByName("red_blue_form")
   
   'Load forms, save the record in the "main" form and start at a new record in the "sub" form
   fmM.load()
   
   if fmM.isLast() AND fmM.Row = 0 then
      fmM.insertRow()
   else
      fmM.updateRow()
   end if

   fmS.load()
   fmS.MoveToInsertRow()

   'Get index for the first column in the "main" forms table
   valMI = fmM.getInt(1)

   'Place index value from above into the second column of the "sub" forms table
   fmS.updateInt(2, valMI)
   
   'Save the record
   fmS.insertRow()
   
   'Refresh the form
   fmS.reload()
   fmS.last()
   
End Sub



The "red_blue" form is where a lot happens. I have a formatted text field that displays the "red_id" for the current record from the recently opened form (see above macro for how it is updated). The "hot" field is displayed in another formatted text field via a parametized query.

The query:

Code:

SELECT DISTINCT "a"."hot" FROM "red" AS "a", "red_blue" AS "b" WHERE "b"."red_id" = "a"."red_id" AND "b"."red_id" = :rid


Using the parametized query I believe is a more involved way of passing the string as opposed to using the setString() method but does not have the aforementioned timing issues.

The assignment of "cool" entries to "hot" entries are displayed in a control grid. The control grid also uses a parametized query to display the assigned entries.

The query:

Code:

SELECT "b"."cool", "b"."blue_id" FROM "red_blue" AS "a", "blue" AS "b" WHERE "a"."blue_id" = "b"."blue_id" AND "a"."red_id" = :rid


Several macros were developed in order to create new assignments, save assignments, open the "blue" form and exit the form.

The macros attached to "new", "save", "exit" and "add" buttons:

Code:

Sub openForm (Event as Object)
   Dim fm as Object       'fm - form
   Dim fmd as Object      'fmd - form document
   Dim fmc as Object      'fmc - form collection
   Dim dbf As Object      'dbForm - database form
   Dim nfmd as Object      'nfmd - new form document
   Dim args(2) as New com.sun.star.beans.PropertyValue
   
   fm = Event.Source.Model.Parent
   fmc = fm.Parent
   fmd = fmc.Parent 
   dbf = fmd.Parent

   args(0).Name = "ActiveConnection"
   args(0).Value = fm.ActiveConnection
   args(1).Name = "OpenMode"
   args(1).Value = "open"
   nfmd = dbf.FormDocuments.loadComponentFromURL("blue","_blank",0,Args())

End Sub

Sub closeForm ()

   thisComponent.CurrentController.Frame.close( TRUE )
   
End Sub

Sub newEntry ()

   Dim fmM as Object
   Dim fmS as Object
   Dim dbf as Object

   dbf = thisComponent.Parent
   
   'Retrieve "main" form
   fmM = dbf.FormDocuments.getByName("red")
   fmM = fmM.Component.DrawPage.Forms.getByName("red_form")
   
   'Retrieve "sub" form
   fmS = dbf.FormDocuments.getByName("red_blue")
   fmS = fmS.Component.DrawPage.Forms.getByName("red_blue_form")
   
   'Load forms and start at a new record in the "sub" form
   fmM.load()
   fmS.load()
   fmS.MoveToInsertRow()
   
   'Retrieve ID from "main" form
   valMI = fmM.getInt(1)

   'Place ID into "sub" form
   fmS.updateInt(2, valMI)
   
   'Insert row
   fmS.insertRow()
   
   'Reload "sub" form
   fmS.reload()
   
   'Go to recently entered record
   fmS.last()
   
End Sub

Sub saveEntry ()

   Dim fmS as Object
   Dim dbf as Object
   Dim row as Integer

   dbf = thisComponent.Parent
   
   'Retrieve "sub" form
   fmS = dbf.FormDocuments.getByName("red_blue")
   fmS = fmS.Component.DrawPage.Forms.getByName("red_blue_form")
   
   'Load form
   fmS.load()
   
   'Get the current row
   if fmS.row = 0 then
      row = fmS.rowCount
   else
      row = fmS.row
   end if

   'Save entry   
   fmS.updateRow()
   
   'Reload "sub" form
   fmS.reload()
   
   'Navigate to current row
   fms.absolute(row)
   
End Sub


The "blue" form is simple in its purpose. New blue entries can be made and once the form is exited the entries in the "red_blue" form are updated.

The macro attached to the exit button:

Code:

REM Subroutine "exit_reload" is attached to an exit button
REM and its function is to exit the current form and reload
REM a listbox in the form that initiated the recently opened
REM form.

Sub exit_reload ()

   Dim dbForms as Object
   Dim formMDoc as Object         
   Dim formMDocName as String
   Dim formSDoc as Object         
   Dim formSDocName as String
   Dim formM as Object            
   Dim formMName as String
   Dim formS as Object
   Dim formSName as String
   Dim lbCtrl as Object
   Dim lbCtrlName as String
   
   'Retrieve the form documents within the database
   dbForms = thisComponent.Parent.getFormDocuments()
   
   'Retrieve the "main" form document
   formMDocName = "red_blue"
   if dbForms.hasByName(formMDocName) then
      formMDoc = dbForms.getByName(formMDocName)
   else
      MsgBox "Nonexistent form document: " & formMDocName
   end if
   
   'Retrieve the "sub" form document; form document initiated by "main"      
   formSDocName = "blue"
   if dbForms.hasByName(formSDocName) then
      formSDoc = dbForms.getByName(formSDocName)
   else
      MsgBox "Nonexistent form document: " & formSDocName
   end if
   
   'Retrieve form within "main" form document
   formMName = "red_blue_form"
   formM = formMDoc.Component.DrawPage.Forms
   if formM.hasByName(formMName) then
      formM = formM.getByName(formMName)
   else
      MsgBox "Nonexistent form: " & formMName
   end if
   
   'Retrieve form within "sub" form document
   formSName = "blue_form"
   formS = formSDoc.Component.DrawPage.Forms
   if formS.hasByName(formSName) then
      formS = formS.getByName(formSName)
   else
      MsgBox "Nonexistent form: " & formSName
   end if
   
   'Obtain listbox control from the "main" form
   lbCtrlName = "coolness"
   if formM.hasByName(lbCtrlName) then
      lbCtrl = formM.getByName(lbCtrlName)
   else
      MsgBox "Nonexistent listbox: " & lbCtrlName
   end if
   
   'Refresh the listbox   
   lbCtrl.refresh()
   
   'Close "sub" form document
   formS.Parent.Parent.CurrentController.Frame.close( TRUE )
   
End Sub


I have outlined my database above for the benefit of others.

Basically, I decided to ditch the getString() and setString() methods in favor of parametized queries that do the job quite nicely and do not involve timing issues.
Back to top
View user's profile Send private message
Voobase
OOo Advocate
OOo Advocate


Joined: 21 Nov 2007
Posts: 400
Location: Australia

PostPosted: Thu Jan 15, 2009 11:00 pm    Post subject: Reply with quote

Hi ch_ta,

Thanks for sharing your method, the code you have written is very clear and neat. I think I understand most of what you have done with your forms and what the code is doing, but I am still a little unsure as to how you have got the parameter query to fit in.

I will detail the way I think your forms work from what I have read... Let me know if I'm too far off track...

From what I understand, you have a "writer doc" form named "red" which displays and enters details into your table called "red" via a form called "red_form". Likewise you have a "writer doc" form called "blue" which displays and enters details into your table called "blue" via a form called "blue_form". You also have a "writer doc" form called "red_blue" based on a table called "red_blue" and with that you can store the many to many relationships between your "red" and "blue" tables.

The way in which you create a new relationship is by pressing a button which is located on the "red" form, which runs the "open_pass" macro so as to open the "red_blue" form. (In the macro you are referring to the "red_blue" form as a "sub" form, even though it is launched in its own "writer doc"). You save your "red" form and then copy the primary key integer value to its foreign key field in the "red_blue" form.

Likewise there is a button to open the "blue" form. Here a new entry can be made and when the form is exited, the listbox (with the "blue" table as its data source) in the "red_blue" form is refreshed. This listbox is responsible for bring the "blue" tables primary key into the many to many relationship.

I am unsure how you are getting the paramater query to do its thing. From what I understand, that sort of query will present you with a dialog box to enter the value to be used in the query. Sorry if the answer is obvious, but I am still learning the potentials of using queries.

Cheers

Voo
Back to top
View user's profile Send private message
RPG
Super User
Super User


Joined: 24 Apr 2008
Posts: 2697
Location: Apeldoorn, Netherland

PostPosted: Fri Jan 16, 2009 3:40 am    Post subject: Reply with quote

Hello ch_ta,

First thank for the code you give.
I do not understand now all thing of the code but I will study it. The most important for me is
Code:
fm = Event.Source.Model.Parent
   fmc = fm.Parent
   fmd = fmc.Parent
   dbf = fmd.Parent

   args(0).Name = "ActiveConnection"
   args(0).Value = fm.ActiveConnection
   args(1).Name = "OpenMode"
   args(1).Value = "open"
   nfmd = dbf.FormDocuments.loadComponentFromURL("blue","_blank",0,Args())


I did search how I could use this methode and or property. It was to difficult for me. I'm glad with the explanation in the code you give. You make also clear to me how I can use the args() array. I did understand it was important. Danny B a person on this forum did also write something about this. I did not understand all the things he wrote, it is not to blame him, I learn not so fast.

I do have one question: The closing of the file. I have notice that it will chance from OOo version to an other one, in the last year.

It is nice.

Romke
Back to top
View user's profile Send private message
RPG
Super User
Super User


Joined: 24 Apr 2008
Posts: 2697
Location: Apeldoorn, Netherland

PostPosted: Sat Jan 17, 2009 4:17 am    Post subject: Reply with quote

Hello Voo and ch_ta,

Closing of the form does not work in OOo 3.0.
I don't if it is a bug and it is known or a form must be closed in an other way.
I don't use loadComponentFromURL but loadComponentWithArguments

http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/OfficeDev/Closing_Documents

The link above looks to explain you have to be more carefull with closing of a form.

It is not so important for me. I only look how I can use the new things they added in OOo

Romke
Back to top
View user's profile Send private message
RPG
Super User
Super User


Joined: 24 Apr 2008
Posts: 2697
Location: Apeldoorn, Netherland

PostPosted: Sun Jan 18, 2009 5:49 am    Post subject: Reply with quote

Hello ch_ta

I did study your code better. I now understand why you use so much form.load.
If I use it, I also get no more an error.

real nice

Romke
Back to top
View user's profile Send private message
ch_ta
General User
General User


Joined: 05 Jan 2009
Posts: 8

PostPosted: Mon Jan 19, 2009 9:40 pm    Post subject: Reply with quote

Romke, yes, we have to be careful in what environment we are working in. I was coding the macros and they all ran fine in OO 2.4.2. Fishy thing is that in OO 2.4.0 the listbox reload method did not seem to work.

Voo, you are spot on in regards to understanding the structure of the forms and embedded functionality. The beauty of the parameter query is that the variable is given a value by the transfer of a parameter. As I transfer the "red_id" value from the "red" form to the "red_blue" form that value is taken as the variable "rid" in the parameter query. The way it is done is by setting up subforms for the "red_blue_form". Within the properties of the subform I can assign the data to consist of the query I provided above. Additionally, I enter for the master field "red_id" (table field for the "red_blue" table) and for the slave field the variable within the parameter query, "rid".

In my premature thinking when I first started with OO base macro programming I referred to a form that I opened, from the Base form window, as the "main" form and other forms (other distinct writer docs) that I opened via a button as "sub" forms. Fortunately, now I have a better grasp of the object hierarchy within OpenOffice to know that that is not the correct terminology.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Base All times are GMT - 8 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group