Hi,

Attached is a small basic file, intended to be embedded in an ODB file.

The file has two main routines:
InsertThisDataForm
InsertFirstDataForm

Datasources tested and comments

dBase - no problems found

HSQLdb - no problems found

MS Access - Image controls will generate error

MySQL - Image controlsl do not write the data to disk, but no error is reported

SQLite3 (odbc) - no support for Image Controls when prepared statements not supported

This started out with trying to help someone with Issue 108377 - this works pretty well for that, even with the problems.

Turns out this is turning into a pretty nice copy record function though...

If you try it (the comments should show you how to use it) let me know if you find any other problems..

Later,

Drew

 

'    Copyright (C) 2010  Andrew 'Drew' Jensen
'        atjen...@openoffice.org
'
'    This program is free software: you can redistribute it and/or modify
'    it under the terms of the GNU General Public License as published by
'    the Free Software Foundation, either version 3 of the License, or
'    (at your option) any later version.
'
'    This program is distributed in the hope that it will be useful,
'    but WITHOUT ANY WARRANTY; without even the implied warranty of
'    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'    GNU General Public License for more details.
'
'    To review a full a copy of the GNU General Public License
'    please see, <http://www.gnu.org/licenses/>.
'
'//     
'//     
'//     The library module was intended to be used as a aid in 
'//     working around an anomily in the 3.2 release of OpenOffice.org Base
'//     
'//     For reference see:
'//     http://www.openoffice.org/issues/show_bug.cgi?id=108377
'//     
'//     The library includes 4 rooutines for use in these
'//     Insert Data Only forms
'//     
'//     Two are suitable for use from menu, toolbar
'//     or dialog displayed by data entry form
'//             
'//     insertdFistDataForm     
'//     reloadFistDataForm
'//
'//             Two when called from a button owned by the dataform
'//             that owns the controls to write to the database
'//
'//             insertThisDataForm
'//     reloadThisDataForm              
'//     
'//     0.1
'//     2010-02-11
'//
'//             two routines do the actual insert
'//
'//             insertDataForm
'//                     SQLite - uses SQL insert statement directly
'//
'//             insertDataFormPS
'//                     all other drivers - uses PreparedStatement component
'//
'               
option explicit 


'//     
'//     reloadFistDataForm
'//     
'//             can be called from menu or toolbar
'//             can be called from dialog displayed by data entry form
'//             
'//             will clear all controls of the first dataform 
'//             on the top most base form window
'
sub reloadFistDataForm()
        '//             
        '//             only want to work with forms
        '//                     
        '//             a Query/dataview window is
        '//             ActiveFrame     = NULL
        '
        if not isNull( 
thisDatabaseDocument.CurrentController.Frame.ActiveFrame.Controller.Model ) then
                '//     
                '//             Report Builder editor
                '
                if not 
thisDatabaseDocument.CurrentController.Frame.ActiveFrame.Controller.Model.supportsService("com.sun.star.sdb.ReportDesign")
 then
                        '//             ASSUME - ASSUME - ASSUME
                        '//             this is a form
                        '
                        
thisDatabaseDocument.CurrentController.Frame.ActiveFrame.Controller.Model.DrawPage.Forms(0).reload
                
                end if
        
        end if

end sub 

'//             
'//             insertFirstDataForm
'//             
'//             can be called from menu or toolbar or Kotkey
'//             can be called from dialog displayed by data entry form
'//             
'//             will write the values from the bound data columns controls
'//             of the first dataform on the top most base form window
'
sub insertFirstDataForm()
        '//             
        '//             only want to work with forms
        '               
        if not isNull( 
thisDatabaseDocument.CurrentController.Frame.ActiveFrame.Controller.Model ) then
                '//     
                '//             Report Builder editor
                '                               
                if not 
thisDatabaseDocument.CurrentController.Frame.ActiveFrame.Controller.Model.supportsService("com.sun.star.sdb.ReportDesign")
 then
                        '//             
                        '//             ASSUME - ASSUME - ASSUME
                        '//             this is a form
                        '
                        if InStr( thisDataBaseDocument.dataSource.URL, 
"sdbc:odbc:SQLite3" ) = 1 then                   
                                '//             
                                '// ODBC/SQLite does not support prepared 
statements
                                '
                                InsertDataForm( 
thisDatabaseDocument.CurrentController.Frame.ActiveFrame.Controller.Model.DrawPage.Forms(0)
 )   
                                
                        else
                                '//             
                                '// everything elese does ?
                                '       
                                InsertDataFormPS( 
thisDatabaseDocument.CurrentController.Frame.ActiveFrame.Controller.Model.DrawPage.Forms(0)
 ) 
                                
                        end if 
                        
                end if
                
        end if
        
end sub 

'//     
'//     reloadThisDataForm
'//             
'//             can be called from a button that has a dataform as parent
'
sub reloadThisDataForm( oEvent as object )

        oEvent.Source.Model.Parent.reload

end sub 

'//             
'//             insertThisDataFormPS
'//             
'//             can be called from a button that has a dataform as parent
'
sub insertThisDataForm( oEvent as object )
        '//             
        '// ODBC/SQLite does not support prepared statements
        '
        if InStr( thisDataBaseDocument.dataSource.URL, "sdbc:odbc:SQLite3" ) = 
1 then                   
        
                InsertDataForm( oEvent.Source.Model.Parent )
        
        else
                '//             
                '// everything elese does ?
                '       
                InsertDataFormPS( oEvent.Source.Model.Parent )
        
        end if 
        
end sub

'//             
'//             insertDataForm
'//                     do it
'
sub InsertDataFormPS(oDataForm as object )
        dim CurrentConnection
        dim CurrentControl
        dim cntr, fldcnt
        dim strCmdFirst, strCmdLast, strTableName, SQLCmd, QuoteString
        dim QryComposer
        dim CurrentColumn
        dim strdata
        dim prepStatement
        dim bStream
        dim cntUsed     
        '//             
        '//             use the connection that is
        '//             used by the datatform control
        '
        CurrentConnection = oDataForm.ActiveCOnnection 
        '//             
        '//             only inerested in quote used for identifieers
        '
        QuoteString = CurrentConnection.MetaData.IdentifierQuoteString
        '//             
        '//             SingleSelectQueryComposer
        '//             replaces the old query composer 
        '//             
        '//             the old composer is still available
        '//             with 
        '//             CurrentConnection.CreateComposer
        '//             
        '//             The old composer however will 
        '//             not allow us to work with queries
        '//             which Alias column names
        '//             
        '
        QryComposer = CurrentConnection.createInstance( 
"com.sun.star.sdb.SingleSelectQueryComposer" ) 
        '//             
        '//             populate the composer with the
        '//             current dataforms SQL command
        '
        QryComposer.Query = oDataForm.ActiveCommand

        
'*************************************************
'
'       TODO -
'       
'*************************************************
'       
'       
'       ensure that the control with focus
'       at the time of a menu/toolbar event
'       does a commit to push the data from 
'       the GUI control to the bound data 
'       control
'       
'               
'*************************************************

        cntUsed = 0

        '//             
        '//             build the two parts of 
        '//             of an SQL insert statement
        '//                     
        '
        for cntr = 0 to QryComposer.Columns.count - 1           
                if      NOT QryComposer.Columns(cntr).isAutoIncrement _
                        AND NOT QryComposer.Columns(cntr).AggregateFunction _
                        AND NOT QryComposer.Columns(cntr).Function  then
                                
                        '//             
                        '//             a secondary counter
                        '//             parameter count may be less then
                        '//             composer column count
                        '
                        cntUsed = cntUsed + 1

                        '//             use the singleQueryComposer 
                        '//             for the column's real names
                        '
                        strCmdFirst = strCmdFirst + QuoteString + 
QryComposer.Columns(cntr).RealName + QuoteString
        
                        '//             with parameters
                        '
                        strCmdLast = strCmdLast + " ? "                         
                                
        
                        if cntr <> QryComposer.Columns.count - 1 then
                                strCmdFirst = strCmdFirst + + ", "
                                strCmdLast = strCmdLast + ", "                  
                        end     if              
        
                end if
                
        next
        '//             
        '//             if not all columns will be sent
        '//             to the database engine
        '//             remove the last comma
        '               
        if cntUsed < QryComposer.Columns.count -1 then
                strCmdFirst = left( strCmdFirst , len( strCmdFirst  ) - 2 )
                strCmdLast = left( strCmdLast, len( strCmdLast ) - 2 )
        end if
        '//             
        '//             build the final SQL statement
        '//     
        '//                     MySQL native connector requires schema 
(catalog) name along with table name
        '
        if InStr( thisDataBaseDocument.DataSource.URL, "sdbc:mysql" ) = 1 then
                '//     
                '//     
                '//             requited when using  a prepared statements 
                '//             with the native connector
                '//                                                     
                '//             dataform.updateSchema returns ""
                '//             so instead the catalog set in the connection
                '
                strTableName = QuoteString + CurrentConnection.Catalog + 
QuoteString + "." + QuoteString + QryComposer.Tables(0).Name + QuoteString

        else
                '//     
                '//             otherwise no catalog (schema) required
                '//             True for embedded HSQLdb, dBase, MS Access
                '
                strTableName = QuoteString + QryComposer.Tables(0).Name + 
QuoteString
                
        end if
        '//             
        '//             assemble the sql
        '
        SQLCmd = "INSERT INTO " + strTableName + " ( " + strCmdFirst + " ) 
VALUES ( " + strCmdLast + " )"
        '//     
        '//             pass it to the database engine
        '       
        prepStatement = CurrentConnection.prepareStatement( SQLCmd )
        '//                     
        '//             prepared statements start counting at 1
        '//                     go figure
        '
        cntUsed = 0
        for cntr = 0 to QryComposer.Columns.count -1 ' oDataForm.Columns.count  
-1
                CurrentColumn = oDataForm.Columns(cntr)         
                '//             
                '//             don't include auto, aggreg, func fields
                '
                if      NOT QryComposer.Columns(cntr).isAutoIncrement _
                        and NOT QryComposer.Columns(cntr).AggregateFunction _
                        and NOT QryComposer.Columns(cntr).Function then

                        '//             
                        '//             a secondary counter
                        '//             parameter count may be less then
                        '//             composer column count
                        '
                        cntUsed = cntUsed + 1
                        '//             
                        '//             binary data gets special treatment
                        '
                        if      CurrentColumn.Type = 
com.sun.star.sdbc.DataType.LONGVARBINARY _
                                or CurrentColumn.Type = 
com.sun.star.sdbc.DataType.VARBINARY  _
                                or CurrentColumn.Type = 
com.sun.star.sdbc.DataType.BLOB then                    
                                '//
                                '//             MySQL native connector requires 
setBlob
                                '       
                                if InStr( thisDataBaseDocument.DataSource.URL, 
"sdbc:mysql" ) = 1 then
        
                                        bStream = CurrentColumn.getBlob
                        
                                        if not CurrentColumn.wasNULL then
                                
                                                prepStatement.setBlob( cntUsed, 
bStream )

                                        else
                                                '//             
                                                '//             different types 
have different nulls
                                                '
                                                prepStatement.setNull( cntUsed, 
CurrentColumn.Type )
                                        
                                        end if
                                

                                else
                                        '//                     HSQLdb use 
setBinaryStream
                                        '//                             
                                        bStream = CurrentColumn.getBinaryStream

                                        if not CurrentColumn.wasNULL then
                                
                                                prepStatement.setBinaryStream( 
cntUsed, bStream, bStream.length )
                                
                                        else
                                                '//             
                                                '//             different types 
have different nulls
                                                '
                                                prepStatement.setNull( cntUsed, 
CurrentColumn.Type )
                                                
                                        end if
                                
                                end if  '// not a binary type
                                                
                        else            
                                '//             
                                '//             everything else pass as string
                                '
                                strdata = CurrentColumn.getString
                                if not CurrentColumn.wasNULL then
                                
                                        prepStatement.setString( cntUsed, 
strdata )
                                        
                                else

                                        prepStatement.setNull( cntUsed, 
CurrentColumn.Type )

                                end if
                        
                        end if
                
                end if
                
        next
        '//             
        '//             set error trap
        '
        on error goto insertDataFormSQLite
        '//             
        '//             execute the insert
        '
        prepStatement.executeUpdate
        '//             
        '//             clean up the GUI controls
        '//             by reseting the dataform
        '//             
        oDataForm.Reload
        '//             
        '//     and exit                
        exit sub
                
insertDataFormSQLite:   
                MsgBox "Error " & Err & ": " & Error$ + chr(13) + "At line : " 
+ Erl + chr(13) + Now , 16 ,"<< insertDataForm >>"
                

end sub


'//             
'//             insertDataForm
'//                     execute SQL command
'//                     binary data not supported
'//                     SQLite3
'//             
sub InsertDataForm(oDataForm as object )
        dim CurrentConnection
        dim CurrentControl
        dim cntr, fldcnt
        dim strCmdFirst, strCmdLast, SQLCmd, QuoteString
        dim QryComposer
        dim CurrentColumn
        dim strdata
        dim cntUsed

        '//             
        '//             use the connection that is
        '//             used by the datatform control
        '//             
        CurrentConnection = oDataForm.ActiveCOnnection 

        '//             
        '//             only inerested in quote used for identifieers
        '//             
        QuoteString = CurrentConnection.MetaData.IdentifierQuoteString

        '//             
        '//             use this for getting different
        '//             parts of the SQL command used
        '//             by the dataform control
        '//             in our case here
        '//             the table name for the SQL statement
        '//             
        QryComposer = CurrentConnection.createInstance( 
"com.sun.star.sdb.SingleSelectQueryComposer" ) 

        '//             
        '//             populate the composer with the
        '//             current dataforms SQL command
        '//             
        QryComposer.Query = oDataForm.ActiveCommand

        '//             
        '//             build the two parts of 
        '//             of an SQL insert statement
        '//                     
        '//             
        '//             iterate over the contols
        '//             to extract the column names
        '//             from the bound data controls
        '//             
        '//             makse sure variables as null
        strCmdFirst = ""
        strCmdLast = ""
        
        '//
        '//     ensure that data in GUI conttol is
        '//     written to the bound data controls
        '//
        '//             no commit for image controls?
        '//
        '//   

'*************************************************
'
'       This loop adds significant time ?
'       
'*************************************************
'       dim impId
'       dim top
'       top = oDataForm.Count
'       cntr = 0
'       
'       do
'               CurrentControl = oDataForm.ControlModels(cntr)
'               impID = oDataForm.ControlModels(cntr).ImplementationId(0)
'               if impID <> 14 AND impID <> 97 then 
'                       if not isNull( CurrentControl.BoundField ) then
'                               CurrentControl.Commit
'                       end if
'               end if
'               cntr = cntr + 1                 
'       loop while cntr < top
'               
'*************************************************


                for cntr = 0 to oDataForm.Columns.count - 1
                        CurrentColumn = oDataForm.Columns(cntr)         
                        if      CurrentColumn.Type <> 
com.sun.star.sdbc.DataType.LONGVARBINARY _
                                and CurrentColumn.Type <> 
com.sun.star.sdbc.DataType.VARBINARY  _
                                and CurrentColumn.Type <> 
com.sun.star.sdbc.DataType.BLOB _
                                and     NOT 
QryComposer.Columns(cntr).isAutoIncrement _
                                and NOT 
QryComposer.Columns(cntr).AggregateFunction _
                                and NOT QryComposer.Columns(cntr).Function then
                                
                                '//             
                                '//             include only those controls 
types
                                '//             that support bound data controls
                                '//             
                                '//             
                                '//             reversed order
                                '//             form can have control models 
after the last 
                                '//             data control
                                '
                                cntUsed = cntUsed + 1
                                strCmdFirst = strCmdFirst + QuoteString + 
QryComposer.Columns(cntr).RealName + QuoteString
                                
                                strdata = CurrentColumn.getString
                                
                                if NOT CurrentColumn.wasNull then

                                        strCmdLast = strCmdLast + " '" + 
strdata  + " '"                                                                

                                else

                                        strCmdLast = strCmdLast + " NULL "

                                end if
                                
                                if cntr <> oDataForm.Columns.count - 1 then
                                        strCmdFirst = strCmdFirst + + ", "
                                        strCmdLast = strCmdLast + ", "
                                end if                                  
                                        
                        end if  

                next
                
                '//             
                '//             if not all columns will be sent
                '//             to the database engine
                '//             remove the last comma
                '               
                if cntUsed < QryComposer.Columns.count -1 then
                        strCmdFirst = left( strCmdFirst , len( strCmdFirst  ) - 
2 )
                        strCmdLast = left( strCmdLast, len( strCmdLast ) - 2 )
                end if
                

                SQLCmd = "INSERT INTO " + QuoteString + 
QryComposer.Tables(0).Name + QuoteString + " ( " + strCmdFirst + " ) VALUES ( " 
+ strCmdLast + " )"

                dim oStatement
                oStatement =  CurrentConnection.createStatement
                
                on error goto insertDataFormSQLite
                oStatement.executeUpdate( SQLCmd )
                
                '//             
                '//             clean up the GUI controls
                '//             by reseting the dataform
                '//             
                oDataForm.Reload
                
                '//             
                '//     and exit                
                exit sub
                
insertDataFormSQLite:   
                MsgBox "Error " & Err & ": " & Error$ + chr(13) + "At line : " 
+ Erl + chr(13) + Now , 16 ,"<< insertDataForm >>"
                
end sub


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@dba.openoffice.org
For additional commands, e-mail: dev-h...@dba.openoffice.org

Reply via email to