ARRAY will fill a range of rows and columns in a COM object with values from a comma separated string.
Syntax:COMObject.Range(A1:B1).Value = ARRAY(A comma separated list of "literal strings" or numbers) Return Value:
Parameters:
|
' BCX COM Demos *** com_test4 *** ' Creates Excel.Application, demonstration of ARRAY keyword. ' Requirements: MS Excel ' By Ljubisa Knezevic BCX_SHOW_COM_ERRORS(TRUE) DIM app as OBJECT COMSET app = CREATEOBJECT("Excel.Application") app.workbooks.add app.visible = TRUE app.ActiveSheet.Range("B2:K2").Value = ARRAY("Week1","Week2", "Week3","Week4", "Week5", "Week6", "Week7", "Week8","Week9", "Week10") app.ActiveSheet.Range("B3:k3").Value = ARRAY("67", "87", "5", "9", "7", "45", "45", "54", "54", "10") app.ActiveSheet.Range("B4:k4").Value = ARRAY("10", "10", "8", "27", "33", "37", "50", "54", "10", "10") app.ActiveSheet.Range("B5:k5").Value = ARRAY("23", "3", "86", "64", "60", "18", "5", "1", "36", "80") app.ActiveSheet.Cells(3,1).Value="Hello" app.ActiveSheet.Cells(4,1).Value="From BCX" app.ActiveSheet.Cells(5,1).Value="Console program!" DIM temp_var$ temp_var$ = app.ActiveSheet.Cells(3,1).Value MSGBOX temp_var$, "value of cell(3,1)", 4096 MSGBOX "BCX COM Example!" & CRLF$ & _ "Using Office automation to manipulate Excel." &CRLF$ & _ "Program will close Excel in 1 second.","finished!", 4096 SLEEP(1000) app.activeworkbook.saved = TRUE app.quit COMSET app = NOTHING
INITSAFEARRAY creates a SAFEARRAY structure, allocates and initializes the data for the array and passes, by reference, a pointer to the new SAFEARRAY structure.
In the Syntax description below, two dimensions are used as an example. However, up to ten dimensions can be specified when using the INITSAFEARRAY function.
Syntax:HRslt = INITSAFEARRAY(safearrayptr AS PTR PTR, _ variabletype AS VARTYPE, _ dimensions AS INTEGER, _ lowerbound1 AS INTEGER, _ numberofelements1 AS INTEGER, _ lowerbound2 AS INTEGER, _ numberofelements2 AS INTEGER, _ ...) Return Value:
Parameters:
|
In the Syntax description below, two dimensions are used as an example. However, up to ten dimensions can be specified when using the ARRAYPUTELEMENT function.
Syntax:ARRAYPUTELEMENT(safearrayptr AS PTR, _ vardata AS VARTYPE, _ dimensions AS INTEGER, _ dim1 AS INTEGER, _ dim2 AS INTEGER, _ ...) Parameters:
|
In the Syntax description below, two dimensions are used as an example. However, up to ten dimensions can be specified when using the ARRAYGETELEMENT function.
Syntax:ARRAYGETELEMENT(safearrayptr AS PTR, _ vardata AS VARTYPE, _ dimensions AS INTEGER, _ dim1 AS INTEGER, _ dim2 AS INTEGER, _ ...) Parameters:
|
DESTROYSAFEARRAY destroys a SAFEARRAY structure and all the data in the array.
Syntax:HRslt = DESTROYSAFEARRAY(safearrayptr) Return Value:
|
This example contains two parts. The first part creates a Microsoft Access database in which data will be created for retrieval by the second part of the example. The second part of the example will retrieve the data and place it in a Microsoft Excel spreadsheet. Please note that the example below requires the Excel_Constants.inc file which is available for download at
https://bcxbasiccoders.com/archives/YahooGroups/Com/Excel_Constants.inc
Part One: Translate, compile and run the following code.
BCX_SHOW_COM_ERRORS(TRUE) DIM szDatabase$ DIM oConn AS OBJECT DIM rs AS OBJECT DIM Provider$ DIM Sql$ 'Create Database szDatabase$ = APPEXEPATH$ & "MYDB.MDB" IF EXIST(szDatabase$) THEN KILL szDatabase$ CreateAccessDatabase(szDatabase$) 'Connect to Database Provider$ = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & szDatabase$ COMSET oConn = CREATEOBJECT("ADODB.Connection") oConn.OPEN Provider$ ' Create Student table Sql$ = "CREATE TABLE tblStudents (Student_Number COUNTER PRIMARY KEY, FirstName TEXT(24), LastName TEXT(24), Address TEXT(30), City TEXT(28), State TEXT(2), ZipCode TEXT(5))" oConn.Execute Sql$ ' Create Grades table Sql$ = "CREATE TABLE tblGrades (Student_Number INT, Semester INT, Score INT)" oConn.Execute Sql$ ' Add students Sql$ = "INSERT INTO tblStudents (FirstName, LastName, Address, City, State, ZipCode ) VALUES ('Larry', 'Stooge', 'Address', 'City', 'St', 'Zip')" oConn.Execute Sql$ Sql$ = "INSERT INTO tblStudents (FirstName, LastName, Address, City, State, ZipCode ) VALUES ('Moe', 'Stooge', 'Address', 'City', 'St', 'Zip')" oConn.Execute Sql$ Sql$ = "INSERT INTO tblStudents (FirstName, LastName, Address, City, State, ZipCode ) VALUES ('Curly', 'Stooge', 'Address', 'City', 'St', 'Zip')" oConn.Execute Sql$ ' Add some grades COMSET rs = CREATEOBJECT("ADODB.recordset") rs.OPEN "SELECT FirstName, LastName, Student_Number FROM tblStudents", oConn, 3, 3 DIM A$ DIM B$ DIM C$ DIM D$ DIM rc DIM i DIM j DO rc = rs.EOF IF rc <> 0 THEN EXIT LOOP C$ = rs.fields("Student_Number") C$ = ENC$(C$,ASC("'")) FOR i = 1 TO 4 j = 70 + 30 * RND A$ = ENC$(STR$(i),ASC("'")) B$ = ENC$(STR$(j),ASC("'")) Sql$ = "INSERT INTO tblGrades (Student_Number, Semester, Score) VALUES (" & C$ & "," & A$ & "," & B$ & ")" oConn.Execute Sql$ NEXT rs.movenext LOOP rs = NOTHING 'show the data that was put into the database DIM sSelectSQL$ sSelectSQL$ = "SELECT tblStudents.FirstName, tblStudents.LastName, tblGrades.Semester, tblGrades.Score " sSelectSQL$ = sSelectSQL$ & "FROM tblGrades INNER JOIN tblStudents ON tblGrades.Student_Number = tblStudents.Student_Number " sSelectSQL$ = sSelectSQL$ & "ORDER BY tblStudents.FirstName, tblStudents.LastName, tblGrades.Semester" COMSET rs = CREATEOBJECT("ADODB.recordset") rs.OPEN sSelectSQL$, oConn, 3, 3 DO rc = rs.EOF IF rc <> 0 THEN EXIT LOOP A$ = rs.fields("FirstName") B$ = rs.fields("LastName") C$ = rs.fields("Semester") D$ = rs.fields("Score") PRINT A$;" ";B$;" Semester ";C$;" Score ";D$ rs.movenext LOOP ' Clean up rs = NOTHING oConn = NOTHING PAUSE SUB CreateAccessDatabase (DBname$) RAW Provider$ RAW oDB AS OBJECT COMSET oDB = CREATEOBJECT("ADOX.Catalog") Provider$ = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & DBname$ oDB.Create Provider$ COMSET oDB = NOTHING END SUB ' End CreateAccessDatabase
Part Two: Translate, compile and run the following code in the same directory as Part One.
BCX_SHOW_COM_ERRORS(TRUE) $INCLUDE "Excel_Constants.inc" DIM sDest$ DIM szDatabase$ DIM oConn AS OBJECT DIM oRecSet AS OBJECT DIM sProvider$ DIM iCols DIM iRows 'Connect to Database szDatabase$ = APPEXEPATH$ & "MYDB.MDB" sProvider$ = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & szDatabase$ COMSET oConn = CREATEOBJECT("ADODB.Connection") IF BCX_GET_COM_STATUS(&oConn) = FALSE THEN MSGBOX "Failed to create oConn object" CALL SetObjects2Nothing() END = 1 END IF oConn.Open sProvider$ COMSET oRecSet = CREATEOBJECT("ADODB.recordset") IF BCX_GET_COM_STATUS(&oRecSet) = FALSE THEN MSGBOX "Failed to create oRecSet object" CALL SetObjects2Nothing() END = 1 END IF oRecSet.Open "SELECT * FROM tblStudents", oConn, 3, 3 iCols = oRecSet.recordcount iCols++ oRecSet = NOTHING COMSET oRecSet = CREATEOBJECT("ADODB.recordset") IF BCX_GET_COM_STATUS(&oRecSet) = FALSE THEN MSGBOX "Failed to create oRecSet object" CALL SetObjects2Nothing() END = 1 END IF oRecSet.Open "SELECT Max(tblGrades.Semester) AS MaxOfSemester FROM tblGrades;", oConn, 3, 3 iRows = oRecSet.fields("MaxOfSemester") iRows++ oRecSet = NOTHING DIM psA AS SAFEARRAY PTR DIM hRET AS HRESULT DIM vArray AS VARIANT DIM pVariant AS VARIANT PTR DIM lComVariant AS VARIANT DIM sBuf$ hRET = INITSAFEARRAY(psA, VT_VARIANT, 2, 0, iRows, 0, iCols) IF hRET THEN CALL Error(hRET) CALL SetObjects2Nothing() END = 1 END IF ' Set the safe arraydescriptor in VARIANT vArray.vt = VT_ARRAY | VT_VARIANT vArray.parray = psA ' SafeArrayAccessData hRET = SafeArrayAccessData(psA, (VOID PTR PTR)&pVariant) IF hRET THEN CALL Error(hRET) DESTROYSAFEARRAY(psA) CALL SetObjects2Nothing() END = 1 END IF ' Get data values for the safe array DIM sSelectSQL$ sSelectSQL$ = "SELECT tblStudents.Student_Number, tblStudents.FirstName, tblStudents.LastName, tblGrades.Semester, tblGrades.Score " sSelectSQL$ = sSelectSQL$ & "FROM tblGrades INNER JOIN tblStudents ON tblGrades.Student_Number = tblStudents.Student_Number " sSelectSQL$ = sSelectSQL$ & "ORDER BY tblStudents.FirstName, tblStudents.LastName, tblGrades.Semester" COMSET oRecSet = CREATEOBJECT("ADODB.recordset") IF BCX_GET_COM_STATUS(&oRecSet) = FALSE THEN MSGBOX "Failed to create oRecSet object" DESTROYSAFEARRAY(psA) CALL SetObjects2Nothing() END = 1 END IF oRecSet.Open sSelectSQL$, oConn, 3, 3 DIM iCol DIM iRow DIM iRecSetFlag DIM iSN DIM iLastSN DIM sFioRecSettName$ DIM sLastName$ DIM iScore iCol = 0 iLastSN = 0 DO iRecSetFlag = oRecSet.EOF IF iRecSetFlag <> 0 Then EXIT Loop ' VARIANT_BOOL returns -1 for FALSE iSN = oRecSet.fields("Student_Number") IF iSN <> iLastSN THEN iLastSN = iSN iCol++ sFioRecSettName$ = oRecSet.fields("FirstName") sLastName$ = oRecSet.fields("LastName") sBuf$ = sFioRecSettName$ & " " & sLastName$ str2variant(sBuf,lComVariant) ARRAYPUTELEMENT(psA,lComVariant, 2, 0, iCol) END IF iRow = oRecSet.fields("Semester") iScore = oRecSet.fields("Score") lComVariant.vt = VT_I4 lComVariant.intVal = iScore ARRAYPUTELEMENT(psA,lComVariant, 2, iRow, iCol) ARRAYGETELEMENT(psA,lComVariant, 2, iRow, 0) IF lComVariant.vt <> VT_BSTR THEN sBuf$ = "Semester" & STR$(iRow) str2variant(sBuf,lComVariant) ARRAYPUTELEMENT(psA,lComVariant, 2, iRow, 0) END IF oRecSet.movenext LOOP oConn.Close oRecSet = NOTHING oConn = NOTHING hRET = SafeArrayUnaccessData(psA) IF hRET THEN CALL Error(hRET) DESTROYSAFEARRAY(psA) CALL SetObjects2Nothing() END = 1 END IF DIM oExcel AS OBJECT DIM oBook AS OBJECT DIM oSheet AS OBJECT DIM oRange AS OBJECT DIM xlCharts AS OBJECT DIM myChart AS OBJECT DIM chartPage AS OBJECT DIM sSaveAs$ 'Start a new workbook in Excel COMSET oExcel = CREATEOBJECT("Excel.Application") IF BCX_GET_COM_STATUS(&oExcel) = FALSE THEN MSGBOX "Failed to create oExcel object" DESTROYSAFEARRAY(psA) CALL SetObjects2Nothing() END = 1 END IF COMSET oBook = oExcel.Workbooks.Add IF BCX_GET_COM_STATUS(&oBook) = FALSE THEN MSGBOX "Failed to create oBook object" DESTROYSAFEARRAY(psA) CALL SetObjects2Nothing() END = 1 END IF COMSET oSheet = oBook.Worksheets(1) IF BCX_GET_COM_STATUS(&oSheet) = FALSE THEN MSGBOX "Failed to create oSheet object" DESTROYSAFEARRAY(psA) CALL SetObjects2Nothing() END = 1 END IF DIM iC1, iC2 iC1 = IMOD((iCols-1),26) iC2 = (iCols-1) / 26 IF iC2 = 0 THEN sDest$ = "A1:" & CHR$(iC1+65) & TRIM$(STR$(iRows)) ELSE sDest$ = "A1:" & CHR$(iC2+65) & CHR$(iC1+65) & TRIM$(STR$(iRows)) END IF oSheet.Range(sDest$).Value = vArray 'psA ' oSheet.Range(sDest$).ColumnWidth = 11 COMSET xlCharts = oSheet.ChartObjects() IF BCX_GET_COM_STATUS(&xlCharts) = FALSE THEN MSGBOX "Failed to create xlCharts object" CALL SetObjects2Nothing() END = 1 END IF COMSET myChart = xlCharts.Add(10, 80, 300, 250) IF BCX_GET_COM_STATUS(&myChart) = FALSE THEN MSGBOX "Failed to create myChart object" CALL SetObjects2Nothing() END = 1 END IF COMSET chartPage = myChart.Chart IF BCX_GET_COM_STATUS(&chartPage) = FALSE THEN MSGBOX "Failed to create chartPage object" CALL SetObjects2Nothing() END = 1 END IF 'SET chartPage = NOTHING COMSET oRange = oSheet.Range(sDest$) IF BCX_GET_COM_STATUS(&oRange) = FALSE THEN MSGBOX "Failed to create oRange object" CALL SetObjects2Nothing() END = 1 END IF 'SET oRange = NOTHING chartPage.SetSourceData(oRange, xlColumns) chartPage.ChartType = xlColumnClustered 'Save the Workbook and Quit Excel sSaveAs$ = APPEXEPATH$ & "CHART_FROM_ACCESS.XLS" oBook.SaveAs sSaveAs$ CALL SetObjects2Nothing() ' Free SafeArray hRET = DESTROYSAFEARRAY(psA) IF hRET THEN CALL Error(hRET) CALL SetObjects2Nothing() END = 1 END IF END = 0 SUB SetObjects2Nothing () IF BCX_GET_COM_STATUS(&oRecSet) THEN oConn.Close COMSET oRecSet = NOTHING END IF IF BCX_GET_COM_STATUS(&oConn) THEN oConn.Close COMSET oConn = NOTHING END IF IF BCX_GET_COM_STATUS(&oRange) THEN COMSET oRange = NOTHING IF BCX_GET_COM_STATUS(&chartPage) THEN COMSET chartPage = NOTHING IF BCX_GET_COM_STATUS(&myChart) THEN COMSET myChart = NOTHING IF BCX_GET_COM_STATUS(&xlCharts) THEN COMSET xlCharts = NOTHING IF BCX_GET_COM_STATUS(&oSheet) THEN COMSET oSheet = NOTHING IF BCX_GET_COM_STATUS(&oBook) THEN COMSET oBook = NOTHING IF BCX_GET_COM_STATUS(&oExcel) THEN oExcel.Quit COMSET oExcel = NOTHING END IF END SUB SUB DEBUGLOGGER (sDEBUG$) OPEN "ERROR.LOG.TXT" FOR APPEND AS FPAPP FPRINT FPAPP, sDEBUG$ CLOSE END SUB SUB Error (hError AS HRESULT) SELECT CASE hError CASE S_OK '"Success." CASE DISP_E_BADINDEX DEBUGLOGGER("The specified index was invalid.") CASE E_INVALIDARG DEBUGLOGGER("One of the arguments is invalid.") CASE E_OUTOFMEMORY DEBUGLOGGER("Memory could not be allocated for the element.") CASE DISP_E_ARRAYISLOCKED DEBUGLOGGER("The array is currently locked.") CASE ELSE RAW sBUF$ sprintf(sBUF,"Error %i (0x%X)",hError,hError) DEBUGLOGGER(sBUF) END SELECT END SUB