这段代码是vckbase上徐景周先生的一个例子中的一段(我改了一下),Commit函数的作用我想就是建表。  不过如果表中加入的项是INTEGER型的,则在excel中显示正确,但是加入CHAR型的数据时(比如加入名字“老李”),在excel相应的项中显示“ ‘老李  ”,也就是说前面多了一个‘ 号。因此所有的表头因为是字符串所以都有一个‘ 号。
  由于我不懂sql的语法,所以猜测是在程序执行sql语句时(建表的时候)相应的sql语法的错误。  请各位高手指点一下。  源码来自这个地址:http://www.vckbase.com/document/viewdoc/?id=693
bool CSpreadSheet::Commit()
{
if (m_bExcel) // If file is an Excel spreadsheet
{
m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog); if (m_bAppend)
{
// Delete old sheet if it exists
m_stempString= "[" + m_sSheetName + "$A1:IV65536]";
m_stempSql.Format ("DROP TABLE %s", m_stempString);
try
{
m_Database->ExecuteSQL(m_stempSql);
}
catch(CDBException *e)
{
m_sLastError = e->m_strError;
m_Database->Close();
return false;
}

// Create new sheet
m_stempSql.Format("CREATE TABLE [%s$A1:IV65536] (", m_sSheetName);

for (int i = 0; i < m_aFieldNames.GetSize(); i++)
{
if( m_aFieldNames.GetAt(i) == "姓名" )
{
m_stempSql = m_stempSql + 
 "[" + m_aFieldNames.GetAt(i) +"]" +
 " CHAR(255), ";
}
else if( m_aFieldNames.GetAt(i) == "年龄" )
{
m_stempSql = m_stempSql + 
 "[" + m_aFieldNames.GetAt(i) +"]" +
 " INTEGER, ";
}
else if( m_aFieldNames.GetAt(i) == "性别" )
{
m_stempSql = m_stempSql + 
 "[" + m_aFieldNames.GetAt(i) +"]" +
 " CHAR(255), ";
}
else if( m_aFieldNames.GetAt(i) == "生日" ) 
{
m_stempSql = m_stempSql + 
 "[" + m_aFieldNames.GetAt(i) +"]" +
 " DATE, ";
}
// m_stempSql = m_stempSql + "[" + m_aFieldNames.GetAt(i) +"]" + " char(255), ";
}
m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
m_stempSql += ")"; }// end of if (m_bAppend)
else
{
// Create new sheet
m_stempSql.Format("CREATE TABLE [%s] (", m_sSheetName);

for (int i = 0; i < m_aFieldNames.GetSize(); i++)
{
if( m_aFieldNames.GetAt(i) == "姓名" )
{
m_stempSql = m_stempSql + 
 "[" + m_aFieldNames.GetAt(i) +"]" +
 " CHAR(255), ";
}
else if( m_aFieldNames.GetAt(i) == "年龄" )
{
m_stempSql = m_stempSql + 
 "[" + m_aFieldNames.GetAt(i) +"]" +
 " INTEGER, ";
}
else if( m_aFieldNames.GetAt(i) == "性别" )
{
m_stempSql = m_stempSql + 
 "[" + m_aFieldNames.GetAt(i) +"]" +
 " CHAR(255), ";
}
else if( m_aFieldNames.GetAt(i) == "生日" ) 
{
m_stempSql = m_stempSql + 
 "[" + m_aFieldNames.GetAt(i) +"]" +
 " CHAR(255), ";
}
// m_stempSql = m_stempSql + "[" + m_aFieldNames.GetAt(i) +"]" + " char(255), ";
}
m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
m_stempSql += ")";
} try
{
m_Database->ExecuteSQL(m_stempSql);
if (!m_bAppend)
{
m_dTotalColumns = m_aFieldNames.GetSize();
m_bAppend = true;
}
}
catch(CDBException *e)
{
m_sLastError = e->m_strError;
m_Database->Close();
return false;
} // Save changed data
for (int k = 1; k < m_dTotalRows; k++)
{
ReadRow(m_atempArray, k+1); // Create Insert SQL
m_stempSql.Format("INSERT INTO [%s$A1:IV%d] (", m_sSheetName, k);
for (int i = 0; i < m_atempArray.GetSize(); i++)
{
m_stempString.Format("[%s], ", m_aFieldNames.GetAt(i));
m_stempSql = m_stempSql + m_stempString;
}
m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
m_stempSql += ") VALUES (";
for (int j = 0; j < m_atempArray.GetSize(); j++)
{
m_stempString.Format("'%s', ", m_atempArray.GetAt(j));
m_stempSql = m_stempSql + m_stempString;
}
m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
m_stempSql += ")"; // Add row
try
{
m_Database->ExecuteSQL(m_stempSql);
}
catch(CDBException *e)
{
m_sLastError = e->m_strError;
m_Database->Close();
return false;
}
}
m_Database->Close();
m_bTransaction = false;
return true;
}
else // if file is a text delimited file
{
try
{
CFile *File = NULL;
File = new CFile(m_sFile, CFile::modeCreate | CFile::modeWrite  | CFile::shareDenyNone);
if (File != NULL)
{
CArchive *Archive = NULL;
Archive = new CArchive(File, CArchive::store);
if (Archive != NULL)
{
for (int i = 0; i < m_aRows.GetSize(); i++)
{
Archive->WriteString(m_aRows.GetAt(i));
Archive->WriteString("\r\n");
}
delete Archive;
delete File;
m_bTransaction = false;
return true;
}
delete File;
}
}
catch(...)
{
}
m_sLastError = "Error writing file\n";
return false;
}
}

解决方案 »

  1.   

    m_stempString.Format("'%s', ", m_atempArray.GetAt(j));
    这句有点怪
      

  2.   

    用odbc不方便规定单元格的格式,建议通过automatin 调用excel
    参考
    http://www.fruitfruit.com/vc/activex/excelauto.cpp
      

  3.   

    else if( m_aFieldNames.GetAt(i) == "年龄" )
    {
    m_stempSql = m_stempSql + 
     "[" + m_aFieldNames.GetAt(i) +"]" +
     " INTEGER, ";}
    ......
    m_stempString.Format("'%s', ", m_atempArray.GetAt(j));
    这行。
    当你的字段类型是INTEGER或者是date类型时候。
    你传入的应该是数字类型或者是日期类型的数据。
    但到了这行以后它把这些类型都转换成了字符类型(对于日期类型的数据将会报错!)。
    (这样就算你可以正确插入也已经是偏离了题意)需要在
    m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
    m_stempSql += ") VALUES (";
    for (int j = 0; j < m_atempArray.GetSize(); j++)
    {
    m_stempString.Format("'%s', ", m_atempArray.GetAt(j));
    m_stempSql = m_stempSql + m_stempString;
    }
    这里更改。
      

  4.   

    zhangqu_980371(能坚持一辈子的东西太少):   不知道我的理解是否正确,请指教:如果某个表项是INTEGER型的,那么当把字符串“27”通过sql语句写入的话,系统会自动将该字符串转换成TINTEGER型的27。
       所以我一直认为所有insert的值都是字符串型的,最后系统将他们转换成相应的实际类型。
      

  5.   

    呵呵,系统不会自动转换的。
    你创建的字段类型是INTEGER数字类型的表,你的sql语句插入时必须是数字类型。
    例如:age是INTEGER类型
    insert into test(name,age)
    values('test',1000)这个1000是不能用''引起来的。
    insert into test(name,age)
    values('test',‘1000’)
    就是错误的。
      

  6.   

    masterz(www.fruitfruit.com):
      非常感谢你的指点。我也很想用你的方法试试,不过我想知道这种方法在多线程的情况下是否很复杂?
      

  7.   

    zhangqu_980371(能坚持一辈子的东西太少) :
       你的解释我明白了,谢谢。我想我确实在处理的时候没有考虑类型的问题。
       不过,即使我把所有的字段类型都改成CHAR型(包括年龄字段),仍然会出现这个问题:在字段里出现‘ 这个符号。不知道这是不是与Unicode有关?
       另外,请问在sql的create或insert等语句中对于unicode是否需要特殊的处理?
      

  8.   

    关于sql语句的问题我将各位的方法都试了一遍,但是不知为什么还是老样子。文本字段都会有个‘在前头。   实在不行就用自动化的方法。
      

  9.   

    我简化了生成sheet的部分,如下: CDatabase database;
    CString sDriver = "MICROSOFT EXCEL DRIVER (*.XLS)"; // exactly the same name as in the ODBC-Manager
    CString sExcelFile = "c:\\test.xls";                // Filename and path for the file to be created
    CString sSql; {
    // Build the creation string for access without DSN

    sSql.Format("DRIVER={%s};DSN='';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s", sDriver,sExcelFile,sExcelFile);

    // Create the database (i.e. Excel sheet)
    if( database.OpenEx(sSql,CDatabase::noOdbcDialog) )
    {
    // Create table structure
    sSql = "CREATE TABLE demo (Name TEXT,Age NUMBER)";
    database.ExecuteSQL(sSql);

    // Insert data
    sSql = "INSERT INTO demo (Name,Age) VALUES ('Bruno Brutalinsky',45)";
    database.ExecuteSQL(sSql);

    sSql = "INSERT INTO demo (Name,Age) VALUES ('Fritz Pappenheimer',30)";
    database.ExecuteSQL(sSql);

    sSql = "INSERT INTO demo (Name,Age) VALUES ('Hella Wahnsinn',28)";
    database.ExecuteSQL(sSql);
    }      

    // Close database
    database.Close();
    }    这一段够简单了吧,而且都不是unicode字符串,结果还是不行.生成的字段都是" 'NAME "和" 'AGE ",那个可恶的'还留着!
        是不是压根就不能在中文版的windows下生成这种表?
        劳烦大家试试看,我希望是我的错.
      

  10.   

    我无法把‘去掉。
       而自动化效率比较低,因此最终我在网上找到了excel文件的详细格式,因为我需要写入的数据相对比较简单因此采用直接写excel文件的方法解决了问题。
       不过仍然感谢oyljerry(☆勇敢的心☆-Paper Reviewing)、 zhangqu_980371(能坚持一辈子的东西太少)、masterz(www.fruitfruit.com)和carek(新手上路)。
       祝你们新年快乐。