abuly80
asked on
ODBC example in C
Hi all,
I am trying to compile and test an example on reading MS Excel files with C/ODBC, which I found on the web. I am having difficulty compiling it. I am using VC++ 6.0 on Win2K platform.
This is the source:
/* -------------------------- ---------- ---------- ---------- ---------- ---------- --------
 * Program:    odbc_excel
 * Purpose:    C program to demo editing and reading info from an excel file using ODBC.
 * Date:     February, 2003
 * Compiler:   LCC-WIN32
 * Tested On:   Windows 2000 SP3 with Excel 2000
 * Style:     Win32 console application
 * DBMS:     Excel Workbook
 * ODBC:     Assumes Microsoft Excel drivers installed
 * Licence:    If you like this code please go to http://www.thehungersite.com
 *
 * Authorship:
 *      With amendments by anonytmouse for reading and writing Excel worksheets,
 *      and odbc version 3 compliance this is based upon a program
 *      by David Brown which can be found at:
 *      http://www.john.findlay1.btinternet.co.uk/DataBase/database.htm
 *
 *       He in turn acknowledges: ...this is based upon the original program
 *      by Rock Cogar... This can be found at:
 *      http://www.john.findlay1.btinternet.co.uk/Snippets/snip.htm
 *
 *      Some of the excel specific code is inspired by an article and C++ code
 *      by Alexander Mikula which can be found at the following locations:
 *      http://www.codeproject.com/database/excel_odbc_write.asp
 *      http://www.codeguru.com/mfc_database/excel_sheets_using_odbc.shtml
 *     Â
 * -------------------------- ---------- ---------- ---------- ---------- ---------- -------- */
/* Note: This code aims to be ODBC Version 3 compliant. ODBC Version 3
 * was first distributed with Office 97 and Windows 98.
 * This involved replacing the SQLAlloc*, SQLFree* and SQLError functions
 * with SQLAllocHandle, SQLFreeHandle and SQLGetDiagRec functions respectively.
 *
 * Note: The Excel ODBC Driver has some limitations. Specifically, it does
 * not support DELETE statements and should not be used to alter an excel
 * file that is already open in another program.
 *
 * Note on mixed data types:
 * As excel columns do not have 'types', the odbc driver scans the first 8 rows
 * to determine the data type of a column. Values that are not of the determined type
 * will return NULL. The 8 rows value can be changed by changing the
 * TypeGuessRows value in the registry. To force numbers to be entered as text
 * right click a column->click Format Cells->set category to text. However, this will
 * not change existing entries.
 * Information on this and resolutions (IMEX=1 property) can be found at:
 *
 * http://support.microsoft.com/default.aspx?scid=kb;en-us;257819
 * under A Caution about Mixed Data Types (halfway down)
 *
 * http://support.microsoft.com/default.aspx?scid=kb;EN-US;194124 */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sql.h>
#include <sqlext.h>
#pragma lib <ODBC32.lib>
#define SZLEN 50
void process(void);
void dbError( LPSTR lp, SQLSMALLINT handleType, SQLHANDLE handle);
void dbErrorCleanup( LPSTR lp,SQLSMALLINT handleType, SQLHENV henv,SQLHDBC hdbc,SQLHSTMT hstmt);
void dbCleanup(SQLHENV henv,SQLHDBC hdbc,SQLHSTMT hstmt);
BOOL isFileOpen(LPTSTR fileName);
int main(int argc,char *argv[])
{
      process();
      printf("Press any key to continue...");
      getchar();
      return 0;
}
void process(void)
{
      SQLUINTEGER lngSportID;
      SQLCHAR szSportName[SZLEN + 1]; /* Buffers for our field values */
      SQLCHAR blSportOlympic;
      SQLLEN lenInd[3]; /* Variables to contain column status or length info */
      SQLHENV    henv = SQL_NULL_HANDLE;
      SQLHDBC    hdbc = SQL_NULL_HANDLE;
      SQLHSTMT    hstmt = SQL_NULL_HANDLE;
      SQLRETURN  retcode;
      char    szSql[256];
      const char fileName[] = "sports.xls"; /* This can include a path */
      char        szdatabase[256];
      /* Connection String Notes: The excel driver is read only by default.
      * Due to a bug in the driver the FIRSTROWHASNAMES and MAXSCANROWS properties
      * are not supported.
      * Therefore the first row of a sheet will always be considered as column headings.
      * We set EXCLUSIVE to yes so no other program can open the file once
      * we have connected. However, this will not stop us opening a file that
      * is already open. The file will be created if it does not exist. */
      sprintf(szdatabase,"DRIVER =Microsoft Excel Driver (*.xls);CREATE_DB=%s;DBQ=% s;READONLY =FALSE;EXC LUSIVE=Yes ;",fileNam e,fileName );
      /* Check that the file is not already open. Attempting to alter
      * an open excel file will have unpredictable consequences.
      * However, only reading from an open excel file should be alright. */
      if ( isFileOpen(fileName) ) {
           printf("This program can not alter an open excel file.\n");
           printf("Please close the excel file and try again.\n");
           return;
      }
      /* Create the environment handle */
      retcode = SQLAllocHandle(SQL_HANDLE_ ENV, SQL_NULL_HANDLE, &henv);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( "SQLAllocHandle(ENV)",SQL_ HANDLE_ENV ,henv,hdbc ,hstmt);
           return;
      }
      /* Tell the odbc manager that we are an odbc version 3 application
      * This MUST be called before using the environment handle */
      retcode = SQLSetEnvAttr(henv,SQL_ATT R_ODBC_VER SION, (SQLPOINTER) SQL_OV_ODBC3,0);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( "SQLSetEnvAttr()",SQL_HAND LE_ENV,hen v,hdbc,hst mt);
           return;
      }
      /* Create the connection handle */     Â
      retcode = SQLAllocHandle(SQL_HANDLE_ DBC, henv, &hdbc);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( "SQLAllocHandle(DBC)",SQL_ HANDLE_ENV ,henv,hdbc ,hstmt);
           return;
      }
      /* Connect to the database */
      retcode = SQLDriverConnect(hdbc, NULL, (SQLCHAR *)szdatabase, (short) (strlen(szdatabase)+1), NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
      /* If there was a DSN already set-up instead of SQLDriverConnect you could use
      *
      *      retcode = SQLConnect(hdbc, "my_dsn", SQL_NTS, NULL, 0, NULL, 0);
      */
      if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
           dbErrorCleanup( "SQLDriverConnect()",SQL_H ANDLE_DBC, henv,hdbc, hstmt);
           return;
      }
      /* Create the statement handle */
      retcode = SQLAllocHandle(SQL_HANDLE_ STMT,hdbc, &hstmt);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( "SQLAllocHandle(STMT)",SQL _HANDLE_DB C,henv,hdb c,hstmt);
           return;
      }
      /* Execute a CREATE TABLE sql statement */
      lstrcpy( szSql,"CREATE TABLE [Sports] (SportID NUMBER, SportName TEXT,SportOlympic LOGICAL) ");
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           SQLCHAR sqlState[15];
           SQLGetDiagField( SQL_HANDLE_STMT, hstmt,1,SQL_DIAG_SQLSTATE, sqlState,s izeof(sqlS tate),NULL );
           /* We want to ignore the 'This table already exists...' error.
            * This error is mapped to SQLSTATE 42S01 in odbc 3 apps. */
           if ( lstrcmpiA(sqlState,"42S01" ) != 0 ) {
                 dbErrorCleanup( " SQLExecDirect()",SQL_HANDL E_STMT,hen v,hdbc,hst mt);
                 return;
           }
      }
      /* Now we can insert some records. Take note of our emulated autonumber
      * field. If any inserts fail we consider it non-fatal. */
      lstrcpy( szSql,"INSERT INTO [Sports$] (SportID,SportName,SportOl ympic) SELECT IIf( IsNull( MAX(SportID) ),0,MAX(SportID) + 1) AS newID, 'Curling' AS newName,TRUE AS newOlympic From [Sports$]");
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           dbError( " SQLExecDirect()",SQL_HANDL E_STMT,hst mt);
      }
      lstrcpy( szSql,"INSERT INTO [Sports$] (SportID,SportName,SportOl ympic) SELECT IIf( IsNull( MAX(SportID) ),0,MAX(SportID) + 1) AS newID, 'Water Skiing' AS newName,FALSE AS newOlympic From [Sports$]");
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           dbError( " SQLExecDirect()",SQL_HANDL E_STMT,hst mt);
      }
      lstrcpy( szSql,"INSERT INTO [Sports$] (SportID,SportName,SportOl ympic) SELECT IIf( IsNull( MAX(SportID) ),0,MAX(SportID) + 1) AS newID, 'Road Rage' AS newName,TRUE AS newOlympic From [Sports$]");
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           dbError( " SQLExecDirect()",SQL_HANDL E_STMT,hst mt);
      }
      /* Now let's retrieve the records in our table */
      lstrcpy( szSql,"SELECT SportID, SportName, SportOlympic FROM [Sports$] ORDER BY SportName, SportID"); /* Select statement */
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( " SQLExecDirect()",SQL_HANDL E_STMT,hen v,hdbc,hst mt);
           return;
      }
     Â
      /* Now we bind the columns to variables. This means that after each
      * successful call to SQLFetch the variables will contain the values
      * of the columns they are bound to for the current row.
      * Note the last argument specifies the address of an indicater variable.
      * This value is filled with the status or length of the column. */
      retcode = SQLBindCol(hstmt, 1,SQL_C_ULONG , &lngSportID, 0, &lenInd[0] );
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( " SQLBindCol()",SQL_HANDLE_S TMT,henv,h dbc,hstmt) ;
           return;
      }
      /* Note that data for this column will be truncated if it is longer
      * than SZLEN */
      retcode = SQLBindCol(hstmt, 2,SQL_C_CHAR , szSportName, SZLEN, &lenInd[1]);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( " SQLBindCol()",SQL_HANDLE_S TMT,henv,h dbc,hstmt) ;
           return;
      }
      retcode = SQLBindCol(hstmt, 3,SQL_C_BIT , &blSportOlympic, 0, &lenInd[2]);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( " SQLBindCol()",SQL_HANDLE_S TMT,henv,h dbc,hstmt) ;
           return;
      }
      /* Now we loop through each record */
      do {
           /* Retrieve a row */
           retcode = SQLFetch(hstmt);
           if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) {
                 dbError( "SQLFetch()",SQL_HANDLE_ST MT,hstmt);
           }
           if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
                 /* Check our indicater variables. These are filled with the
                 * status or length of the column. Set default values
                 * if a column is NULL. */
                 if (lenInd[0] == SQL_NULL_DATA) lngSportID = 0;
                 if (lenInd[1] == SQL_NULL_DATA) lstrcpy(szSportName,"NONE" );
                 if (lenInd[2] == SQL_NULL_DATA) blSportOlympic = 0;
                 /* SQLFetch has filled our variables with the values of the
                 * current record */
                 fprintf(stdout, "ID: %d\tName: %s\tOlympic: %s\n", lngSportID, szSportName, (blSportOlympic ? "TRUE" : "FALSE") );
           }
      } while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO);
      /* Cleanup time */
      dbCleanup( henv, hdbc, hstmt );
}
// -------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --
void dbError( LPSTR lp, SQLSMALLINT handleType, SQLHANDLE handle) {
      /* Print out error info */
      unsigned char buf[250];
      unsigned char sqlstate[15];
      SQLGetDiagRec( handleType,handle, 1, sqlstate, NULL,buf, sizeof(buf),NULL);
      fprintf(stderr, "%s. %s, SQLSTATE=%s\n",lp, buf, sqlstate);
}
// -------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --
void dbErrorCleanup( LPSTR lp,SQLSMALLINT handleType, SQLHENV henv,SQLHDBC hdbc,SQLHSTMT hstmt) {
      /* Print error info and cleanup */
      SQLHANDLE handle;
      switch (handleType) {
           case SQL_HANDLE_STMT:
                 handle = hstmt;
                 break;
           case SQL_HANDLE_DBC:
                 handle = hdbc;
                 break;
           default:
                 handle = henv;
      }
      if (handle != SQL_NULL_HANDLE) dbError( lp, handleType, handle  );
      dbCleanup(henv, hdbc, hstmt );
}
// -------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --
void dbCleanup(SQLHENV henv,SQLHDBC hdbc,SQLHSTMT hstmt) {
      /* Disconnect, unbind, and free handles */
      if (hstmt != SQL_NULL_HANDLE) {
           SQLFreeStmt(hstmt, SQL_UNBIND);
           SQLFreeHandle(SQL_HANDLE_S TMT,hstmt) ;
      }
      if (hdbc != SQL_NULL_HANDLE) {
           SQLDisconnect(hdbc);
           SQLFreeHandle(SQL_HANDLE_D BC,hdbc);
      }
      if (henv != SQL_NULL_HANDLE) SQLFreeHandle(SQL_HANDLE_E NV,henv);
}
// -------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --
BOOL isFileOpen(LPTSTR fileName) {
      /* Check if another program has a file open */
      HANDLE hFile;
      /* Try to open the file with no sharing rights. This will cause
      * an error if another program has it open */
      hFile = CreateFile(fileName,GENERI C_READ,0,N ULL,OPEN_E XISTING,0, NULL);
      if (hFile == INVALID_HANDLE_VALUE) {
           if (GetLastError() == ERROR_SHARING_VIOLATION) return TRUE; /* Someone has it open */
           else return FALSE; /* probable ERROR_FILE_NOT_FOUND */
      }
      else {
           CloseHandle(hFile);
           return FALSE;
      }
}
--------------------------
These are the errors/warnings I get:
--------------------Config uration: excel_test - Win32 Debug--------------------
Compiling...
odbc_excel.c
E:\excel_test\odbc_excel.c (60) : warning C4068: unknown pragma
E:\excel_test\odbc_excel.c (85) : error C2065: 'SQLLEN' : undeclared identifier
E:\excel_test\odbc_excel.c (85) : error C2146: syntax error : missing ';' before identifier 'lenInd'
E:\excel_test\odbc_excel.c (85) : error C2065: 'lenInd' : undeclared identifier
E:\excel_test\odbc_excel.c (85) : error C2109: subscript requires array or pointer type
E:\excel_test\odbc_excel.c (87) : error C2275: 'SQLHENV' : illegal use of this type as an expression
    c:\program files\microsoft visual studio\vc98\include\sqltyp es.h(71) : see declaration of 'SQLHENV'
E:\excel_test\odbc_excel.c (87) : error C2146: syntax error : missing ';' before identifier 'henv'
E:\excel_test\odbc_excel.c (87) : error C2065: 'henv' : undeclared identifier
E:\excel_test\odbc_excel.c (88) : error C2275: 'SQLHDBC' : illegal use of this type as an expression
    c:\program files\microsoft visual studio\vc98\include\sqltyp es.h(72) : see declaration of 'SQLHDBC'
E:\excel_test\odbc_excel.c (88) : error C2146: syntax error : missing ';' before identifier 'hdbc'
E:\excel_test\odbc_excel.c (88) : error C2065: 'hdbc' : undeclared identifier
E:\excel_test\odbc_excel.c (89) : error C2275: 'SQLHSTMT' : illegal use of this type as an expression
    c:\program files\microsoft visual studio\vc98\include\sqltyp es.h(73) : see declaration of 'SQLHSTMT'
E:\excel_test\odbc_excel.c (89) : error C2146: syntax error : missing ';' before identifier 'hstmt'
E:\excel_test\odbc_excel.c (89) : error C2065: 'hstmt' : undeclared identifier
E:\excel_test\odbc_excel.c (91) : error C2275: 'SQLRETURN' : illegal use of this type as an expression
    c:\program files\microsoft visual studio\vc98\include\sqltyp es.h(62) : see declaration of 'SQLRETURN'
E:\excel_test\odbc_excel.c (91) : error C2146: syntax error : missing ';' before identifier 'retcode'
E:\excel_test\odbc_excel.c (91) : error C2065: 'retcode' : undeclared identifier
E:\excel_test\odbc_excel.c (92) : error C2143: syntax error : missing ';' before 'type'
E:\excel_test\odbc_excel.c (93) : error C2143: syntax error : missing ';' before 'const'
E:\excel_test\odbc_excel.c (94) : error C2143: syntax error : missing ';' before 'type'
E:\excel_test\odbc_excel.c (104) : error C2065: 'szdatabase' : undeclared identifier
E:\excel_test\odbc_excel.c (104) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (104) : warning C4024: 'sprintf' : different types for formal and actual parameter 1
E:\excel_test\odbc_excel.c (104) : error C2065: 'fileName' : undeclared identifier
E:\excel_test\odbc_excel.c (110) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (110) : warning C4024: 'isFileOpen' : different types for formal and actual parameter 1
E:\excel_test\odbc_excel.c (117) : warning C4047: 'function' : 'void ** ' differs in levels of indirection from 'int *'
E:\excel_test\odbc_excel.c (117) : warning C4022: 'SQLAllocHandle' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (120) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (120) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (120) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (126) : warning C4022: 'SQLSetEnvAttr' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (129) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (129) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (129) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (134) : warning C4022: 'SQLAllocHandle' : pointer mismatch for actual parameter 2
E:\excel_test\odbc_excel.c (134) : warning C4047: 'function' : 'void ** ' differs in levels of indirection from 'int *'
E:\excel_test\odbc_excel.c (134) : warning C4022: 'SQLAllocHandle' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (137) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (137) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (137) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (142) : warning C4022: 'SQLDriverConnect' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (142) : warning C4047: 'function' : 'const char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (142) : warning C4024: 'strlen' : different types for formal and actual parameter 1
E:\excel_test\odbc_excel.c (150) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (150) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (150) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (155) : warning C4022: 'SQLAllocHandle' : pointer mismatch for actual parameter 2
E:\excel_test\odbc_excel.c (155) : warning C4047: 'function' : 'void ** ' differs in levels of indirection from 'int *'
E:\excel_test\odbc_excel.c (155) : warning C4022: 'SQLAllocHandle' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (158) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (158) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (158) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (164) : error C2065: 'szSql' : undeclared identifier
E:\excel_test\odbc_excel.c (164) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (164) : warning C4024: 'lstrcpyA' : different types for formal and actual parameter 1
E:\excel_test\odbc_excel.c (165) : warning C4022: 'SQLExecDirect' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (165) : warning C4047: 'function' : 'unsigned char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (165) : warning C4024: 'SQLExecDirect' : different types for formal and actual parameter 2
E:\excel_test\odbc_excel.c (170) : warning C4022: 'SQLGetDiagField' : pointer mismatch for actual parameter 2
E:\excel_test\odbc_excel.c (175) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (175) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (175) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (183) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (183) : warning C4024: 'lstrcpyA' : different types for formal and actual parameter 1
E:\excel_test\odbc_excel.c (184) : warning C4022: 'SQLExecDirect' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (184) : warning C4047: 'function' : 'unsigned char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (184) : warning C4024: 'SQLExecDirect' : different types for formal and actual parameter 2
E:\excel_test\odbc_excel.c (187) : warning C4022: 'dbError' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (190) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (190) : warning C4024: 'lstrcpyA' : different types for formal and actual parameter 1
E:\excel_test\odbc_excel.c (191) : warning C4022: 'SQLExecDirect' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (191) : warning C4047: 'function' : 'unsigned char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (191) : warning C4024: 'SQLExecDirect' : different types for formal and actual parameter 2
E:\excel_test\odbc_excel.c (194) : warning C4022: 'dbError' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (197) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (197) : warning C4024: 'lstrcpyA' : different types for formal and actual parameter 1
E:\excel_test\odbc_excel.c (198) : warning C4022: 'SQLExecDirect' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (198) : warning C4047: 'function' : 'unsigned char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (198) : warning C4024: 'SQLExecDirect' : different types for formal and actual parameter 2
E:\excel_test\odbc_excel.c (201) : warning C4022: 'dbError' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (207) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (207) : warning C4024: 'lstrcpyA' : different types for formal and actual parameter 1
E:\excel_test\odbc_excel.c (208) : warning C4022: 'SQLExecDirect' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (208) : warning C4047: 'function' : 'unsigned char *' differs in levels of indirection from 'int '
E:\excel_test\odbc_excel.c (208) : warning C4024: 'SQLExecDirect' : different types for formal and actual parameter 2
E:\excel_test\odbc_excel.c (211) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (211) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (211) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (222) : warning C4022: 'SQLBindCol' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (222) : error C2109: subscript requires array or pointer type
E:\excel_test\odbc_excel.c (222) : error C2102: '&' requires l-value
E:\excel_test\odbc_excel.c (222) : error C2198: 'SQLBindCol' : too few actual parameters
E:\excel_test\odbc_excel.c (224) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (224) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (224) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (230) : warning C4022: 'SQLBindCol' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (230) : error C2109: subscript requires array or pointer type
E:\excel_test\odbc_excel.c (230) : error C2102: '&' requires l-value
E:\excel_test\odbc_excel.c (230) : error C2198: 'SQLBindCol' : too few actual parameters
E:\excel_test\odbc_excel.c (232) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (232) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (232) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (236) : warning C4022: 'SQLBindCol' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (236) : error C2109: subscript requires array or pointer type
E:\excel_test\odbc_excel.c (236) : error C2102: '&' requires l-value
E:\excel_test\odbc_excel.c (236) : error C2198: 'SQLBindCol' : too few actual parameters
E:\excel_test\odbc_excel.c (238) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (238) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 4
E:\excel_test\odbc_excel.c (238) : warning C4022: 'dbErrorCleanup' : pointer mismatch for actual parameter 5
E:\excel_test\odbc_excel.c (246) : warning C4022: 'SQLFetch' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (249) : warning C4022: 'dbError' : pointer mismatch for actual parameter 3
E:\excel_test\odbc_excel.c (257) : error C2109: subscript requires array or pointer type
E:\excel_test\odbc_excel.c (258) : error C2109: subscript requires array or pointer type
E:\excel_test\odbc_excel.c (259) : error C2109: subscript requires array or pointer type
E:\excel_test\odbc_excel.c (270) : warning C4022: 'dbCleanup' : pointer mismatch for actual parameter 1
E:\excel_test\odbc_excel.c (270) : warning C4022: 'dbCleanup' : pointer mismatch for actual parameter 2
E:\excel_test\odbc_excel.c (270) : warning C4022: 'dbCleanup' : pointer mismatch for actual parameter 3
Error executing cl.exe.
odbc_excel.obj - 34 error(s), 84 warning(s)
-----------------------
I would sicerely appreciate any help.
Thanks in advance.
I am trying to compile and test an example on reading MS Excel files with C/ODBC, which I found on the web. I am having difficulty compiling it. I am using VC++ 6.0 on Win2K platform.
This is the source:
/* --------------------------
 * Program:    odbc_excel
 * Purpose:    C program to demo editing and reading info from an excel file using ODBC.
 * Date:     February, 2003
 * Compiler:   LCC-WIN32
 * Tested On:   Windows 2000 SP3 with Excel 2000
 * Style:     Win32 console application
 * DBMS:     Excel Workbook
 * ODBC:     Assumes Microsoft Excel drivers installed
 * Licence:    If you like this code please go to http://www.thehungersite.com
 *
 * Authorship:
 *      With amendments by anonytmouse for reading and writing Excel worksheets,
 *      and odbc version 3 compliance this is based upon a program
 *      by David Brown which can be found at:
 *      http://www.john.findlay1.btinternet.co.uk/DataBase/database.htm
 *
 *       He in turn acknowledges: ...this is based upon the original program
 *      by Rock Cogar... This can be found at:
 *      http://www.john.findlay1.btinternet.co.uk/Snippets/snip.htm
 *
 *      Some of the excel specific code is inspired by an article and C++ code
 *      by Alexander Mikula which can be found at the following locations:
 *      http://www.codeproject.com/database/excel_odbc_write.asp
 *      http://www.codeguru.com/mfc_database/excel_sheets_using_odbc.shtml
 *     Â
 * --------------------------
/* Note: This code aims to be ODBC Version 3 compliant. ODBC Version 3
 * was first distributed with Office 97 and Windows 98.
 * This involved replacing the SQLAlloc*, SQLFree* and SQLError functions
 * with SQLAllocHandle, SQLFreeHandle and SQLGetDiagRec functions respectively.
 *
 * Note: The Excel ODBC Driver has some limitations. Specifically, it does
 * not support DELETE statements and should not be used to alter an excel
 * file that is already open in another program.
 *
 * Note on mixed data types:
 * As excel columns do not have 'types', the odbc driver scans the first 8 rows
 * to determine the data type of a column. Values that are not of the determined type
 * will return NULL. The 8 rows value can be changed by changing the
 * TypeGuessRows value in the registry. To force numbers to be entered as text
 * right click a column->click Format Cells->set category to text. However, this will
 * not change existing entries.
 * Information on this and resolutions (IMEX=1 property) can be found at:
 *
 * http://support.microsoft.com/default.aspx?scid=kb;en-us;257819
 * under A Caution about Mixed Data Types (halfway down)
 *
 * http://support.microsoft.com/default.aspx?scid=kb;EN-US;194124 */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sql.h>
#include <sqlext.h>
#pragma lib <ODBC32.lib>
#define SZLEN 50
void process(void);
void dbError( LPSTR lp, SQLSMALLINT handleType, SQLHANDLE handle);
void dbErrorCleanup( LPSTR lp,SQLSMALLINT handleType, SQLHENV henv,SQLHDBC hdbc,SQLHSTMT hstmt);
void dbCleanup(SQLHENV henv,SQLHDBC hdbc,SQLHSTMT hstmt);
BOOL isFileOpen(LPTSTR fileName);
int main(int argc,char *argv[])
{
      process();
      printf("Press any key to continue...");
      getchar();
      return 0;
}
void process(void)
{
      SQLUINTEGER lngSportID;
      SQLCHAR szSportName[SZLEN + 1]; /* Buffers for our field values */
      SQLCHAR blSportOlympic;
      SQLLEN lenInd[3]; /* Variables to contain column status or length info */
      SQLHENV    henv = SQL_NULL_HANDLE;
      SQLHDBC    hdbc = SQL_NULL_HANDLE;
      SQLHSTMT    hstmt = SQL_NULL_HANDLE;
      SQLRETURN  retcode;
      char    szSql[256];
      const char fileName[] = "sports.xls"; /* This can include a path */
      char        szdatabase[256];
      /* Connection String Notes: The excel driver is read only by default.
      * Due to a bug in the driver the FIRSTROWHASNAMES and MAXSCANROWS properties
      * are not supported.
      * Therefore the first row of a sheet will always be considered as column headings.
      * We set EXCLUSIVE to yes so no other program can open the file once
      * we have connected. However, this will not stop us opening a file that
      * is already open. The file will be created if it does not exist. */
      sprintf(szdatabase,"DRIVER
      /* Check that the file is not already open. Attempting to alter
      * an open excel file will have unpredictable consequences.
      * However, only reading from an open excel file should be alright. */
      if ( isFileOpen(fileName) ) {
           printf("This program can not alter an open excel file.\n");
           printf("Please close the excel file and try again.\n");
           return;
      }
      /* Create the environment handle */
      retcode = SQLAllocHandle(SQL_HANDLE_
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( "SQLAllocHandle(ENV)",SQL_
           return;
      }
      /* Tell the odbc manager that we are an odbc version 3 application
      * This MUST be called before using the environment handle */
      retcode = SQLSetEnvAttr(henv,SQL_ATT
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( "SQLSetEnvAttr()",SQL_HAND
           return;
      }
      /* Create the connection handle */     Â
      retcode = SQLAllocHandle(SQL_HANDLE_
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( "SQLAllocHandle(DBC)",SQL_
           return;
      }
      /* Connect to the database */
      retcode = SQLDriverConnect(hdbc, NULL, (SQLCHAR *)szdatabase, (short) (strlen(szdatabase)+1), NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
      /* If there was a DSN already set-up instead of SQLDriverConnect you could use
      *
      *      retcode = SQLConnect(hdbc, "my_dsn", SQL_NTS, NULL, 0, NULL, 0);
      */
      if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
           dbErrorCleanup( "SQLDriverConnect()",SQL_H
           return;
      }
      /* Create the statement handle */
      retcode = SQLAllocHandle(SQL_HANDLE_
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( "SQLAllocHandle(STMT)",SQL
           return;
      }
      /* Execute a CREATE TABLE sql statement */
      lstrcpy( szSql,"CREATE TABLE [Sports] (SportID NUMBER, SportName TEXT,SportOlympic LOGICAL) ");
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           SQLCHAR sqlState[15];
           SQLGetDiagField( SQL_HANDLE_STMT, hstmt,1,SQL_DIAG_SQLSTATE,
           /* We want to ignore the 'This table already exists...' error.
            * This error is mapped to SQLSTATE 42S01 in odbc 3 apps. */
           if ( lstrcmpiA(sqlState,"42S01"
                 dbErrorCleanup( " SQLExecDirect()",SQL_HANDL
                 return;
           }
      }
      /* Now we can insert some records. Take note of our emulated autonumber
      * field. If any inserts fail we consider it non-fatal. */
      lstrcpy( szSql,"INSERT INTO [Sports$] (SportID,SportName,SportOl
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           dbError( " SQLExecDirect()",SQL_HANDL
      }
      lstrcpy( szSql,"INSERT INTO [Sports$] (SportID,SportName,SportOl
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           dbError( " SQLExecDirect()",SQL_HANDL
      }
      lstrcpy( szSql,"INSERT INTO [Sports$] (SportID,SportName,SportOl
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           dbError( " SQLExecDirect()",SQL_HANDL
      }
      /* Now let's retrieve the records in our table */
      lstrcpy( szSql,"SELECT SportID, SportName, SportOlympic FROM [Sports$] ORDER BY SportName, SportID"); /* Select statement */
      retcode = SQLExecDirect(hstmt, szSql, SQL_NTS);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( " SQLExecDirect()",SQL_HANDL
           return;
      }
     Â
      /* Now we bind the columns to variables. This means that after each
      * successful call to SQLFetch the variables will contain the values
      * of the columns they are bound to for the current row.
      * Note the last argument specifies the address of an indicater variable.
      * This value is filled with the status or length of the column. */
      retcode = SQLBindCol(hstmt, 1,SQL_C_ULONG , &lngSportID, 0, &lenInd[0] );
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( " SQLBindCol()",SQL_HANDLE_S
           return;
      }
      /* Note that data for this column will be truncated if it is longer
      * than SZLEN */
      retcode = SQLBindCol(hstmt, 2,SQL_C_CHAR , szSportName, SZLEN, &lenInd[1]);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( " SQLBindCol()",SQL_HANDLE_S
           return;
      }
      retcode = SQLBindCol(hstmt, 3,SQL_C_BIT , &blSportOlympic, 0, &lenInd[2]);
      if (retcode != SQL_SUCCESS) {
           dbErrorCleanup( " SQLBindCol()",SQL_HANDLE_S
           return;
      }
      /* Now we loop through each record */
      do {
           /* Retrieve a row */
           retcode = SQLFetch(hstmt);
           if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) {
                 dbError( "SQLFetch()",SQL_HANDLE_ST
           }
           if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
                 /* Check our indicater variables. These are filled with the
                 * status or length of the column. Set default values
                 * if a column is NULL. */
                 if (lenInd[0] == SQL_NULL_DATA) lngSportID = 0;
                 if (lenInd[1] == SQL_NULL_DATA) lstrcpy(szSportName,"NONE"
                 if (lenInd[2] == SQL_NULL_DATA) blSportOlympic = 0;
                 /* SQLFetch has filled our variables with the values of the
                 * current record */
                 fprintf(stdout, "ID: %d\tName: %s\tOlympic: %s\n", lngSportID, szSportName, (blSportOlympic ? "TRUE" : "FALSE") );
           }
      } while (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO);
      /* Cleanup time */
      dbCleanup( henv, hdbc, hstmt );
}
// --------------------------
void dbError( LPSTR lp, SQLSMALLINT handleType, SQLHANDLE handle) {
      /* Print out error info */
      unsigned char buf[250];
      unsigned char sqlstate[15];
      SQLGetDiagRec( handleType,handle, 1, sqlstate, NULL,buf, sizeof(buf),NULL);
      fprintf(stderr, "%s. %s, SQLSTATE=%s\n",lp, buf, sqlstate);
}
// --------------------------
void dbErrorCleanup( LPSTR lp,SQLSMALLINT handleType, SQLHENV henv,SQLHDBC hdbc,SQLHSTMT hstmt) {
      /* Print error info and cleanup */
      SQLHANDLE handle;
      switch (handleType) {
           case SQL_HANDLE_STMT:
                 handle = hstmt;
                 break;
           case SQL_HANDLE_DBC:
                 handle = hdbc;
                 break;
           default:
                 handle = henv;
      }
      if (handle != SQL_NULL_HANDLE) dbError( lp, handleType, handle  );
      dbCleanup(henv, hdbc, hstmt );
}
// --------------------------
void dbCleanup(SQLHENV henv,SQLHDBC hdbc,SQLHSTMT hstmt) {
      /* Disconnect, unbind, and free handles */
      if (hstmt != SQL_NULL_HANDLE) {
           SQLFreeStmt(hstmt, SQL_UNBIND);
           SQLFreeHandle(SQL_HANDLE_S
      }
      if (hdbc != SQL_NULL_HANDLE) {
           SQLDisconnect(hdbc);
           SQLFreeHandle(SQL_HANDLE_D
      }
      if (henv != SQL_NULL_HANDLE) SQLFreeHandle(SQL_HANDLE_E
}
// --------------------------
BOOL isFileOpen(LPTSTR fileName) {
      /* Check if another program has a file open */
      HANDLE hFile;
      /* Try to open the file with no sharing rights. This will cause
      * an error if another program has it open */
      hFile = CreateFile(fileName,GENERI
      if (hFile == INVALID_HANDLE_VALUE) {
           if (GetLastError() == ERROR_SHARING_VIOLATION) return TRUE; /* Someone has it open */
           else return FALSE; /* probable ERROR_FILE_NOT_FOUND */
      }
      else {
           CloseHandle(hFile);
           return FALSE;
      }
}
--------------------------
These are the errors/warnings I get:
--------------------Config
Compiling...
odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
    c:\program files\microsoft visual studio\vc98\include\sqltyp
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
    c:\program files\microsoft visual studio\vc98\include\sqltyp
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
    c:\program files\microsoft visual studio\vc98\include\sqltyp
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
    c:\program files\microsoft visual studio\vc98\include\sqltyp
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
E:\excel_test\odbc_excel.c
Error executing cl.exe.
odbc_excel.obj - 34 error(s), 84 warning(s)
-----------------------
I would sicerely appreciate any help.
Thanks in advance.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER