这段代码是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;
}
}
这句有点怪
参考
http://www.fruitfruit.com/vc/activex/excelauto.cpp
{
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;
}
这里更改。
所以我一直认为所有insert的值都是字符串型的,最后系统将他们转换成相应的实际类型。
你创建的字段类型是INTEGER数字类型的表,你的sql语句插入时必须是数字类型。
例如:age是INTEGER类型
insert into test(name,age)
values('test',1000)这个1000是不能用''引起来的。
insert into test(name,age)
values('test',‘1000’)
就是错误的。
非常感谢你的指点。我也很想用你的方法试试,不过我想知道这种方法在多线程的情况下是否很复杂?
你的解释我明白了,谢谢。我想我确实在处理的时候没有考虑类型的问题。
不过,即使我把所有的字段类型都改成CHAR型(包括年龄字段),仍然会出现这个问题:在字段里出现‘ 这个符号。不知道这是不是与Unicode有关?
另外,请问在sql的create或insert等语句中对于unicode是否需要特殊的处理?
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下生成这种表?
劳烦大家试试看,我希望是我的错.
而自动化效率比较低,因此最终我在网上找到了excel文件的详细格式,因为我需要写入的数据相对比较简单因此采用直接写excel文件的方法解决了问题。
不过仍然感谢oyljerry(☆勇敢的心☆-Paper Reviewing)、 zhangqu_980371(能坚持一辈子的东西太少)、masterz(www.fruitfruit.com)和carek(新手上路)。
祝你们新年快乐。