我正在编写一个小类来与通过COM读取excel文件进行交互。到目前为止一切正常,除非我试图读取单元格的值。
在测试期间,我最初从构造函数调用getCell()
只是为了检查它是否正常工作,一切都很好。一旦我从文件外部开始调用getCell()
,我就获得了LNK2019。
这是一个缩短的样本:
ExcelIO.h
//MicroSoft Office Objects
#import "C:\Program Files (x86)\Common Files\Microsoft Shared\OFFICE14\mso.dll" \
rename("DocumentProperties", "DocumentPropertiesXL") \
rename("RGB", "RBGXL")
//Microsoft VBA Objects
#import "C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"
//Excel Application Objects
#import "C:\Program Files\Microsoft Office\Office14\EXCEL.EXE" \
rename("DialogBox", "DialogBoxXL") rename("RGB", "RBGXL") \
rename("DocumentProperties", "DocumentPropertiesXL") \
rename("ReplaceText", "ReplaceTextXL") \
rename("CopyFile", "CopyFileXL") \
exclude("IFont", "IPicture") no_dual_interfaces
class xlWorksheet {
public:
xlWorksheet(Excel::_WorksheetPtr COMobjWs);
template <class T>
T getCell(int m, int n); // mth row, nth column
template <>
string getCell<string>(int m, int n);
private:
Excel::_WorksheetPtr _COMobjWs {nullptr};
Excel::RangePtr _usedRange {nullptr};
};
// TEMPLATE FUNCTION DEFINITIONS
template <class T>
T xlWorksheet::getCell(int m, int n) {
T _temp;
try {
_temp = _usedRange->Item[m+1][n+1];
}
catch(...) {
_temp = T {};
}
return _temp;
}
template <>
string xlWorksheet::getCell<string>(int m, int n) {
// Get the _bstr_t value
_bstr_t bstrt = getCell<_bstr_t>(m, n);
// Detach the BSTR from the _bstr_t
BSTR bstr = bstrt.Detach();
// Initialize a blank string for the conversion (will be blank if conversion fails)
string _temp;
// Convert the BSTR into string
int len = WideCharToMultiByte(CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL);
if (len > 0)
{
_temp.resize(len);
WideCharToMultiByte(CP_UTF8, 0, bstr, -1, &_temp[0], len, NULL, NULL);
}
delete bstr;
return _temp;
}
ExcelIO.cpp中的xlWorksheet构造函数没什么特别之处,只是读取COM对象并分配私有变量。
您会注意到getCell()
对字符串有一个模板专门化,因为COM喜欢返回_bstr_t
类型,因此专门化只是将_bstr_t
删除为a std::string
。
如果在main.cpp中我包含ExcelIO.h并构造一个xlWorksheet并调用getCell<type>(...);
我收到链接错误。为什么我可以在ExcelIO中完全调用它?
我已经按照相似的建议here,但没有运气。
作为参考,完整的错误是(使用双模板调用时):
LNK2019: unresolved external symbol "public: class _variant_t __thiscall Excel::Range::GetItem(class _variant_t const &,class _variant_t const &)" (?GetItem@Range@Excel@@QAE?AV_variant_t@@ABV3@0@Z) referenced in function "public: double __thiscall xlWorksheet::getCell<double>(int,int)" (??$getCell@N@xlWorksheet@@QAENHH@Z)
答案 0 :(得分:0)
当#import dll / OLB文件时,它应该创建一对自动编译到项目中的文件 - .TLH和.TLI文件。每次导入都应该有一对。 .TLH是标题,.TLI是实现。链接错误似乎表明您正在找到.TLH但由于某种原因,Visual Studio未将.TLI编译到您的项目中。
在项目目录中仔细检查以确保文件存在,并且Excel :: Range :: GetItem()函数同时存在。
尝试从xlWorkSheet类声明中删除专用版本的getCell的空声明。也就是说,删除这一位:
template <>
string getCell<string>(int m, int n);
...然后离开下面的专业化。此外,要么将专业化标记为&#34; inline&#34;或者将它移到完全在课堂内部。
如果这没有帮助,尝试编写一个简单的,常规的函数(不是模板专业化,而是一个函数)来完成你的专业版所做的 - 它返回一个字符串。首先尝试从main.cpp中调用 。你还得到链接错误。
最后如果 没有帮助 - 并且假设TLH / TLI文件在那里并且函数在其中,那么尝试(仅用于测试)手动#include .TLI文件in您的一个CPP文件(或临时将TLI文件添加到您的项目中)并再次构建。你不应该曾经需要在实践中这样做但如果它消除了错误,那么至少它揭示了问题的根源。