title: transferring from PLC (OPC client server Kepware) to MS Access, C
body: <p>I am completely new to working with PLCs, but I have a project that need fetch data from an OPC client server, then send it to an Access database table. The bulk of the code minus OPCWriteGroupItems was from someone else. I am just lost on transferring the data that the get from OPCReadGroupItems to the proper variables in my function OPCWriteGroupItems. I just want to get the values that are read into the variables. Thanks.
  F.Y.I.
  My query statement I know needs to be tweaked so that it will read the variables correctly but that is anouther problem that I am working on. This is the more pressing concern. </p>
  
  <p>Below are the two functions that I spoke of:</p>
  
  <pre><code>//---------------------------------------------------------
  // Read items from an OPC Group
  //---------------------------------------------------------
  
  OPCStat OPCReadGroupItems (int iGrp, struct Var_Stru v[] ) 
  {
  
  HRESULT r1;
  HRESULT *hr;
  OPCITEMSTATE *is;
  int iItem;
  
  OPCStat RetVal=OPCSuccess;
  
  if (pGRPTagSIO[iGrp]) {
  
      if (bOPCDebug) printf("Reading data .... \n");
      r1 = pGRPTagSIO[iGrp]-&gt;Read(OPC_DS_CACHE, 
          OPCDataGroup[iGrp].iNumItems, 
          OPCDataGroup[iGrp].hItem,
          &amp;is, 
          &amp;hr);
  
      if (FAILED(r1)) {
          printf("Error from Read(%lx)\n", r1);
          RetVal = OPCError;
      } else {
  
          // if the read worked then copy results to the v structure based on type
          for (iItem=0;iItem&lt;OPCDataGroup[iGrp].iNumItems;iItem++ ) {
              //printf("Read item= %d, hr= %lx, Quality= %2x", iItem, hr[iItem], is[iItem].wQuality);
              if(!FAILED(hr[iItem])) {
              //  printf("%d", is[iItem].vDataValue.vt);
                  //printf("%d", iGrp);
                  switch(is[iItem].vDataValue.vt) {
  
                      case VT_I2:             //   2
                          v[iItem].iVal = is[iItem].vDataValue.iVal;
                          break;
                      case VT_I4:             //   3
                          v[iItem].lVal = is[iItem].vDataValue.lVal;
                          break;
                      case VT_R4:             //   4
                      //  printf("Z");
                          v[iItem].fVal = is[iItem].vDataValue.fltVal;
                          break;
                      case VT_R8:             //   5
                          v[iItem].dblVal = is[iItem].vDataValue.dblVal;
                          break;
                      case VT_BOOL:           //  11
                          v[iItem].bVal = is[iItem].vDataValue.boolVal;
                          break;
                      case VT_UI1:            //  11
                          printf("TEST");
                          sprintf(v[iItem].cVal, "%s", is[iItem].vDataValue.cVal);
                          printf("%s", v[iItem].cVal);
                          printf("%c", v[iItem].cVal);
                          break;
                      case VT_BSTR:           //   8
                      //  printf("TEST");
                          sprintf(v[iItem].cVal,"%-.*ls", kOPCStringSize,is[iItem].vDataValue.bstrVal );
                          //printf("\n STRING STRING  %s \n", v[iItem].cVal);
                          break;
                      default:
                          break;
                  }
              }
                  if(iGrp &gt;= 0 &amp;&amp; iGrp &lt;=)
                  {
                  stuct_double[iGrp-1][iItem] = v[iItem].dblVal;
                  //  printf("group %d  ", iGrp);
                  //  printf("Tag %i: %10.2f\n", iItem, root_plc[iItem]);
                  }
                  if(iGrp &gt; 0 &amp;&amp; iGrp &lt;= 44)
                  {
                  struc_floats[iGrp-1][iItem] = v[iItem].fVal;
                  //printf("GROUP %d  ", iGrp);
                  //printf("Tag %i: %10.2f\n", iItem, struc_floats[iGrp-1][iItem]);
                  } 
  
                  else
                  {
                  printf("Error reading data item %d\n", iItem);
                  //RetVal=OPCError;  //Make not as severe -- rjf 06/03/02
                  RetVal=OPCWarning;
                  //break;        //Escape the for-loop -- rjf- 5/13/02
                  }
                  */
  
                  pIMalloc-&gt;Free(hr);
                  for (iItem=0;iItem&lt;OPCDataGroup[iGrp].iNumItems;iItem)
                  {
                      VariantClear($is[iItem].vdatavalue)
                  }
                  pIMalloc-&gt;Free(is);
              }
          }
      else{
          RetVal=OPCError;
          }
  
      return (RetVal);
  }
  
  
  
  //-----------------------------------------
  // Write items contained in an OPC Group 
  //-----------------------------------------
  OPCStat OPCWriteGroupItems (int iGrp, struct Var_Stru vOut[] ) 
  {
  
  /* Data Access Method used in this sample */
  const char* DAM = "Direct ODBC";
  
  /* Connection string for Direct ODBC */
  char szDSN[256] = "DSN=Gas_Meter_check;";
  
  HRESULT r1,r2;
  HRESULT *hr;
  VARIANT v[nMaxOPCItems];
  int iItem;
  OPCStat RetVal=OPCSuccess;
  
  if (pGRPTagSIO[iGrp]) {
  
      for (iItem=0;iItem&lt;OPCDataGroup[iGrp].iNumItems;iItem++) {
  
          v[iItem].vt = OPCDataGroup[iGrp].iType;
  
          switch(OPCDataGroup[iGrp].iType) {
  
              case VT_I2:                     //   2
                  v[iItem].iVal = vOut[iItem].iVal;
                  break;
              case VT_I4:                     //   3
                  v[iItem].lVal = vOut[iItem].lVal;
                  break;
              case VT_R4:                     //   4
                  v[iItem].fltVal = vOut[iItem].fVal;
                  break;
              case VT_R8:                     //   5
  
                  v[iItem].dblVal = vOut[iItem].dblVal;
                   HENV    hEnv;    HDBC    hDbc;
  
                  /* ODBC API return status */    RETCODE rc;
  
  int     iConnStrLength2Ptr;
  char    szConnStrOut[256];
  int i= 0;
  char datetime[256];
  double HMCO=1.0;
  double HMR,HMT;
  unsigned char* InsertQuery = "INSERT INTO Data ( [Date / Time], [Hot Strip Mill rate], [Hot Strip Mill Comm Okay], [Hot Strip Mill Total] ) SELECT #datetime# AS Expr1, HMR AS Expr2, 1 AS Expr3, HMCO AS Expr4, HMT AS Expr5;";
  
  SQLCHAR         chval1[128], chval2[128], colName[128];
  int             ret1;
  int             ret2;
  
  /* Number of rows and columns in result set */
  SQLINTEGER      rowCount = 0;
  SQLSMALLINT     fieldCount = 0, currentField = 0;
  HSTMT           hStmt;
  
  /* Allocate an environment handle */
  rc = SQLAllocEnv(&amp;hEnv);
  /* Allocate a connection handle */
  rc = SQLAllocConnect(hEnv, &amp;hDbc);
  
  /* Connect to the TakeCharge database */
  rc = SQLDriverConnect(hDbc, NULL, (unsigned char*)szDSN, 
      SQL_NTS, (unsigned char*)szConnStrOut, 
      255, (SQLSMALLINT*)&amp;iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
  if (SQL_SUCCEEDED(rc)) 
  {
      printf("%s: Successfully connected to database. Data source name: \n  %s\n", 
         DAM, szConnStrOut);
  
      /* Prepare SQL query */
      printf("%s: SQL InsertQuery:\n  %s\n", DAM, InsertQuery);
  
      rc = SQLAllocStmt(hDbc,&amp;hStmt);
      rc = SQLPrepare(hStmt, InsertQuery, SQL_NTS);
  
      /* Excecute the query and create a record set */
      rc = SQLExecute(hStmt); 
      if (SQL_SUCCEEDED(rc)) 
      {
         printf("Executing query...");
         printf("\n");
          }
  
          while (SQL_SUCCEEDED(rc)) 
          {
              printf(" insert passed\n");
              rc = SQLFetch(hStmt);
              rowCount++;
          };         
      }
  else
  {
      printf("%s: Couldn't connect to %s.\n", DAM, szDSN);
  }
  
  /* Disconnect*/
  SQLDisconnect(hDbc);
  
  printf("%s: Cleanup. Done.\n", DAM);
  
  
                  break;
              case VT_BOOL:                   //  11
                  v[iItem].bVal = vOut[iItem].bVal;
                  break;
              case VT_BSTR:                   //   8
              //  printf(" In Message value (VT_BSTR) = %s \n",vOut[iItem].cVal );
  
                  r2 = LPTSTR_to_BSTR ( &amp;v[iItem].bstrVal , vOut[iItem].cVal);
                  if ( r2 != S_OK ) {
                      printf ("error in memory \n");
                      RetVal = OPCError;
                  }
  
              //  printf(" Write Msg value(VT_BSTR) = %ls \n", v[iItem].bstrVal );
                  report(0,0,0, "STRINGS data %s",vOut[iItem].cVal);
  
                  break;
              default:
                  printf(" value(unknown type:%d) ", OPCDataGroup[iGrp].iType );
                  RetVal = OPCError;
                  break;
          }
          //if (bOPCDebug) DumpVariant(OPCDataGroup[iGrp].cTagNames[iItem], &amp;v[iItem]);
      }
  
      r1 = pGRPTagSIO[iGrp]-&gt;Write(
          OPCDataGroup[iGrp].iNumItems,
          OPCDataGroup[iGrp].hItem, 
          v, 
          &amp;hr);
  
      if (FAILED(r1))
      {
          printf("Error from Write(%lx)\n", r1);
          RetVal = OPCError;
  
      } else  {
          //if (bOPCDebug) printf("Successful Write ... \n");
  
          // Clear the Variant
          for (iItem=0;iItem&lt;OPCDataGroup[iGrp].iNumItems;iItem++) {
              VariantClear(&amp;v[iItem]);
          }
  
          pIMalloc-&gt;Free(hr);     
      }
  } else {
      RetVal = OPCError;
  }
  
  return(RetVal);
  }
  </code></pre>