1、Sample program: grouping of repetitive functions on User Archives in one function. QUESTION: How can I reduce the C code with scripts for accessing User Archive? ANSWER: If you program scripts for accessing User Archive, then there are large volumes of code for the administration tasks. This code is
2、 the same for accessing all User Archives. The example here shows an option for grouping the administration tasks together in one function. The script structure looks like this for standard programming methods: 1. Generating the sorting and filtering conditions 2. Setting up a connection to the User
3、 Archive uaConnect uaQueryArchiveByName if error: return 3. Setting the sorting and filtering conditions uaArchiveSetFilter uaArchiveSetSort 4. Opening the query uaArchiveOpen 5. Actually working with the query Read, write, delete, insert and so on. 6. Clearing down the connection to the User Archiv
4、e uaArchiveClose uaReleaseArchive uaDisconnect If you program everything with fault check in one function, the function becomes too large and unclear. If you take a close look at the list above, you will be able to see that only points 1 and 5 change from case to case. All the other points remain th
5、e same no matter what structure the User Archive has. You can split the above structure into 3 functions. 1. The task-related function takes care of point 1. It generates the filters and sorting conditions. 2. A general function that encapsulates all administration actions. This function applies for
6、 ALL User Archives. The function receive a callback function as parameter. This callback function is called either for each entry in the query or just once for the entire archive. 3. A callback function, this function process point 5. This division means that you dont have to worry about the adminis
7、tration actions. You program just one function for query generation and one archive-related function, which processes the archive entries. In the following example we use the function uaUtilityEnumRecords. Function description: BOOL uaUtilityEnumRecords( Const char* pszArchiveName , const char* lpsz
8、Filter, const char* lpszSort, BOOL ( UserFunc )( UAHARCHIVE* phUA, void* pUserData ), void* pUserData ) Parameters: pszArchiveName: Pointer to a zero-terminated string. The string contains the name of the archive as it appears in the User Archive editor. lpszFilter: Pointer to a zero-terminated stri
9、ng. The string contains the filter condition for the archive. The pointer can also be ZERO. lpszSort: Pointer to a zero-terminated string. The string contains the sorting condition for the archive. The pointer can also be ZERO. UserFunc: Name of a callback function. The function is called for each e
10、ntry if you transfer a filter. The function is called once for the entire archive if you do not transfer a filter. The function must be of the following type: BOOL ( UserFunc )( UAHARCHIVE* phUA, void* pUserData ). pUserData: Pointer to user data. The pointer is forwarded without modification to the
11、 callback function. Return value: The function returns the value TRUE if: no faults have occurred during connection setup and clear-down. the callback function always returns TRUE. Otherwise the value FALSE is returned. Function: The uaUtilityEnumRecords function carries out the following steps: 1.
12、Sets up connection to the User Archive. 2. Sets the filter and sorting conditions if they are transferred. 3. Opens the query. 4. If no filter has been set, the function calls the callback function with the “handle“ to the archive. If the filter exists, the callback function is called in a loop for
13、each entry in the query with the “handle“ to an entry. As soon as the CB function returns the value FALSE, the loop is terminated. The function uaUtilityEnumRecords then returns the FALSE. 5. After the callback function has been processed, the connection to the archive is set up. You see the code of
14、 the function in the following PDF document: uaUtilityEnumRecords_1.pdf ( 7 KB ) 代码: #include “apdefap.h“ BOOL uaUtilityEnumRecords( const char* pszArchiveName , const char* lpszFilter, const char* lpszSort, BOOL ( UserFunc ) ( UAHARCHIVE* phUA, void* pUserData ), void* pUserData ) /* Function creat
15、e a Query for a User Archive specified by Filter and sort condition. Function calls for each Record in Query User function if Filter specified. If not filter spezified function calls user function only one time. Parameter hArchive: Handle to a User Archive lpszFilter: Pointer to Zerro Terminated str
16、ing with Filter for User Archive. If Pointer isnt NULL function make new Query from Archive, and calls for EACH record User Function ! If Pointer is NULL: Function create conection to User Archive whithout filter. In this Case user function is called only ONE TIME ! lpszSort: pointer to zeroterminat
17、ed string with sort condition lpFunc: Pointer to User Function. pUserData: Pointer to Parameter Struct for User Function. */ BOOL returnCode = TRUE; const char* funcName = “uaUtilityEnumRecords“ ; UAHCONNECT hConnect ; BOOL returnCode =TRUE; / Get Connection to User Archives returnCode = uaConnect(
18、if( !returnCode | !hConnect ) returnCode = FALSE; printf( “%s fault in uaConnect rn“, funcName ); else / Get Handle to Actual Archive. UAHARCHIVE hArchive; if ( ! uaQueryArchiveByName( hConnect, pszArchiveName , returnCode = FALSE; else if( lpszFilter ) returnCode = uaArchiveSetFilter( hArchive, lps
19、zFilter ); if( lpszSort ) returnCode = ( returnCode if( !returnCode ) printf(“%s: uaArchiveSetFilter rn“, funcName ); else / Open Data returned by Query if( uaArchiveOpen( hArchive ) ) / If Filter specified: Go to First Record in Query if ( ! lpszFilter ) / if none Filter specified: call user funkct
20、ion one Time only if( !( returnCode = UserFunc( else / Filter angegeben ( Filter specified ) BOOL isRecord = uaArchiveMoveFirst ( hArchive ) ; / If Filter specified: For each Record in Query : iterate all Records and Call User Function while( isRecord isRecord = uaArchiveMoveNext( hArchive ); /. whi
21、le / if !Filter if ( !uaArchiveClose ( hArchive ) printf(“%s error in uaArchiveClose ! rn “, funcName) ; returnCode = FALSE ; / uaArchiveOpen / SetFilter if( !uaReleaseArchive ( hArchive ) ) printf(“%s error in uaReleaseArchive! rn “, funcName) ; returnCode = FALSE ; / uaQueryArchiveByName if( !uaDi
22、sconnect( hConnect ) ) printf(“%s error in uaDisconnect ! rn “, funcName) ; returnCode = FALSE ; / if( !returnCode | !hConnect ) return returnCode; Interface of the callback functions: phUA: Pointer to a User Archive handle. The “handle“ can refer to the entire archive or just one single entry. pUse
23、rData: Pointer to the user data. Return value: In the case of faults, functions should return the value FALSE. Sample project: The sample project demonstrates the application of the function uaUtilityEnumRecords. The sample project was created with WinCC V5.0. You can also use the function with WinC
24、C V 4.02. The sample project contains sample User Archive called “JobData“. The archive has two columns. One column for the product designation and the other column for the product quantity. In the start image there are four buttons that access the archive. The “Insert Job“ button inserts a new line
25、 in the archive. InsertButton_1.pdf ( 3 KB ) Button Insert Job #include “apdefap.h“ void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName) if( uaUtilityEnumRecords( “JobData“ , NULL , NULL , InsertJobCB , NULL ) ) printf( “Insert O.K. rn“ ); else printf( “Insert failed ! r
26、n“ ); Function InsertJobCB #include “apdefap.h“ BOOL InsertJobCB( UAHARCHIVE* phArchive , void* pUserData ) BOOL rc = TRUE; / Return code char* szProductName = GetTagCharWait( “ProductName“ ); / read name of product long lPartsToProd = ( long ) GetTagWord( “BlanksToProduce“ ); / read number of parts
27、 if( ! uaArchiveSetFieldValueString( *phArchive, 1 , szProductName ) | / write productname to archive ! uaArchiveSetFieldValueLong( *phArchive, 2 , lPartsToProd ) ) / write number of parts to archive printf( “InsertJobCB: error on writing to record rn“ ); rc = FALSE ; else if( !uaArchiveInsert( *phA
28、rchive ) ) / insert new line in archive printf( “InsertJobCB: error on updating archive rn“ ); rc = FALSE ; return rc; The “Change Job“ button sets the quantity for the specified job ID. Change_Job_Button_1.pdf ( 3 KB ) Button Change Job #include “apdefap.h“ void OnClick(char* lpszPictureName, char*
29、 lpszObjectName, char* lpszPropertyName) long presetValue = GetTagWord( “PresetNumber“ ); if( uaUtilityEnumRecords( “JobData“, “ID0“ , NULL , SetPartsNumberCB , else printf( “Preseting Values failed rn“ ); Funktion SetPartsNumberCB #include “apdefap.h“ BOOL SetPartsNumberCB( UAHARCHIVE* phArchive ,
30、void* pUserData ) BOOL rc = TRUE ; / return code if( ! uaArchiveSetFieldValueLong( *phArchive, 2 , *(long*)pUserData ) ) / write number of parts to archive printf( “SetPartsNumberCB: error on writing to Archive rn“ ); rc = FALSE ; else if( !uaArchiveUpdate( *phArchive ) ) / update archive line print
31、f( “SetPartsNumberCB: error on updating Archive rn“ ); rc = FALSE ; return rc ; The “Get Job with biggest Amount“ button provides the name for the job with the largest quantity specified. Get_biggestJob_Button_1.pdf ( 3 KB ) Button Get Job with biggest amount #include “apdefap.h“ void OnClick(char*
32、lpszPictureName, char* lpszObjectName, char* lpszPropertyName) char productname100; if ( uaUtilityEnumRecords(“JobData“, NULL , “Amount DESC“ , GetNameCB , productname ) ) SetTagChar( “ProductNameBiggestJob“ , productname ); printf( “ Get Name O.K. rn“ ) ; else printf( “ Get Name failed rn“ ) ; Func
33、tion GetNameCB #include “apdefap.h“ BOOL GetNameCB( UAHARCHIVE* phArchive , void* pUserData ) if( !uaArchiveMoveFirst( *phArchive ) ) return FALSE ; return uaArchiveGetFieldValueString( *phArchive, 1 , pUserData, 50 ); The “Preset No. of Parts Amount“ button sets the specified amount for each job. P
34、reset_No_of_PartsButton_1.pdf ( 3 KB ) Button Preset No. of Parts #include “apdefap.h“ void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName) long id = GetTagDWord( “ID“ ) ; long parts = GetTagWord( “BlanksToProduce“ ); char filter 20 ; sprintf( filter, “ID=%d“, id ); if (
35、 uaUtilityEnumRecords(“JobData“, filter, NULL , SetPartsNumberCB, else printf( “Update failed ! rn“ ); Funktion SetPartsNumberCB #include “apdefap.h“ BOOL SetPartsNumberCB( UAHARCHIVE* phArchive , void* pUserData ) BOOL rc = TRUE ; / return code if( ! uaArchiveSetFieldValueLong( *phArchive, 2 , *(lo
36、ng*)pUserData ) ) / write number of parts to archive printf( “SetPartsNumberCB: error on writing to Archive rn“ ); rc = FALSE ; else if( !uaArchiveUpdate( *phArchive ) ) / update archive line printf( “SetPartsNumberCB: error on updating Archive rn“ ); rc = FALSE ; return rc ; The following Zip archi
37、ve contains the sample project. Load the archive onto the hard disk. Unpack the archive in a directory. Now you can open and test the project. Observe the archive window and the global script diagnostics windows. UAExample_1.exe ( 356 KB ) Important: The sample program is freeware. Every user can us
38、e, copy or forward this program FREE OF CHARGE. The authors and owners of this program take no responsibility whatsoever for the functionality and compatibility of this software. Use of the software is entirely at the users own risk. Since this software is free of charge, there is no warranty, no claim for error correction and no hotline support.