OLE操作EXCEL出现的问题

sxqinge 2012-11-02 02:43:46
提示错误:EOleSysError with message'因为应用程序正在发送一个输入同步呼叫,所以无法执行传出的呼叫'.
请问这个错误一般预示着什么问题呢?我的程序是把妖哥的稍微改动了下,如下:
1.创建EXCEL文件:

void CreateExcelFiles(AnsiString filename)
{
Variant vExcelApp, vSheet;
try
{
CoInitialize(NULL);
vExcelApp = Variant::CreateObject("Excel.Application");
}
catch(...)
{
MessageBox(0, "启动 Excel 出错, 可能是没有安装Excel.",
"WARNING", MB_OK | MB_ICONERROR);
vExcelApp = Unassigned;
return;
}
// 隐藏Excel界面
vExcelApp.OlePropertySet("Visible", false);
// 新建一个工作表
vExcelApp.OlePropertyGet("Workbooks").OleFunction("Add", 1); // 工作表
// 操作这个工作表
vSheet = vExcelApp.OlePropertyGet("ActiveWorkbook")
.OlePropertyGet("Sheets", 1);

// 表格的列数
int nColCount(8);
// 设置单元格的宽度
for(int i=0; i<nColCount; i++)
{
int nColWidth = 28;
vExcelApp.OlePropertyGet("Columns", i + 1)
.OlePropertySet("ColumnWidth", nColWidth / 2.6);
}

......//其他代码

vExcelApp.OlePropertyGet("ActiveWorkbook")
.OleFunction("SaveAs", filename.c_str());
vExcelApp.OleFunction("Quit");
vSheet = Unassigned;
vExcelApp = Unassigned;
CoUninitialize();
}

2.创建成功表格后,就每采集到一个数据,就存入该文件中:

void AddData(AnsiString filename)
{
Variant vExcelApp, vSheet;
try
{
// CoInitialize(NULL);
vExcelApp = Variant::CreateObject("Excel.Application"); //这里出现问题
}
catch(...)
{
MessageBox(0, "启动 Excel 出错, 可能是没有安装Excel.",
"WARNING", MB_OK | MB_ICONERROR);
vExcelApp = Unassigned;
return;
}
// 隐藏Excel界面
vExcelApp.OlePropertySet("Visible", false);
vExcelApp.OlePropertyGet("workbooks").OleFunction("open",filename.c_str());
// 操作这个工作表
vSheet = vExcelApp.OlePropertyGet("ActiveWorkbook")
.OlePropertyGet("Sheets", 1);

int nRow = vSheet.OlePropertyGet("UsedRange").OlePropertyGet("Rows")
.OlePropertyGet("Count") + 1;

......//这里是插入数据代码

vExcelApp.OlePropertyGet("ActiveWorkbook").OleFunction("Save");
vExcelApp.OlePropertySet("DisplayAlerts",false);
vExcelApp.OleFunction("Quit");
vSheet = Unassigned;
vExcelApp = Unassigned;
// CoUninitialize();
}

问题就是在AddData函数中,代码的红色标识处,在该处设置断点,走下去的时候就提示如上的错误了,网上没找到相关资料,我现在只是顺序操作,没有其他进程调用这个AddData函数,怎么会出现这样的问题呢?不得其解,求解释。
...全文
944 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
bamboo_lady 2014-09-17
  • 打赏
  • 举报
回复
多线程中Excel资源互斥
sxqinge 2012-11-05
  • 打赏
  • 举报
回复
妖哥,我网上粗略的找了下资料,关于排队机制的不是很多,可以给个资料链接看看么?
ccrun.com 2012-11-05
  • 打赏
  • 举报
回复
涉及多线程么?有可能是AddData函数正在操作Excel对象的时候,又有调用AddData造成抢资源。 应该搞个排队机制。
sxqinge 2012-11-05
  • 打赏
  • 举报
回复
回妖哥: 9L的代码问题就是,在执行添加函数AddData()时,当我调用OLE函数时,就发生错误:EOleSysError with message'因为应用程序正在发送一个输入同步呼叫,所以无法执行传出的呼叫'. 回10楼: 我也觉得应该就是你所说的这个字面意思,但是我先前输入已完成了,为什么还会出现这个提示呢?
ccrun.com 2012-11-05
  • 打赏
  • 举报
回复
9楼的代码以后,出现什么问题呢?
弥尔顿 2012-11-05
  • 打赏
  • 举报
回复
会不会是你要输出的那个Excel正在进行的操作有冲突? 字面上理解是在等输入,但是你那句是要获取他的信息来输出. 我之前做的时候也是,要修改单元格里面的值,如果我让单元格处于编辑状态,然后再使用修改的话就会报出“被呼叫方拒绝接收呼叫” 不是太懂.给点参考而已
sxqinge 2012-11-05
  • 打赏
  • 举报
回复
妖哥,我这里是要对多个表格同时操作,抄读多个串口传过来的消息,然后按串口号将每个表数据给保存起来。按照你的思路,我写了3个函数: CreateExcelFiles(const int Port); //创建EXCEL文件 AddData(const int Port); //添加数据 CloseExcelSave(const int Port); //关闭EXCEL文件 实现过程如下:

void TfrmMain::CreateExcelFiles(const int Port)
{
	try
	{
		CoInitialize(NULL);
		m_vExcelApp[Port] = Variant::CreateObject("Excel.Application");
	}
	catch(...)
    {
        MessageBox(0, "启动 Excel 出错, 可能是没有安装Excel.",
                "WARNING", MB_OK | MB_ICONERROR);
		m_vExcelApp[Port] = Unassigned;
        return;
    }
    // 隐藏Excel界面
	m_vExcelApp[Port].OlePropertySet("Visible", false);
	// 新建一个工作表
	m_vExcelApp[Port].OlePropertyGet("Workbooks").OleFunction("Add", 1); // 工作表
	// 操作这个工作表
	m_vWorkBook[Port] = m_vExcelApp[Port].OlePropertyGet("ActiveWorkbook");
	m_vSheet[Port] = m_vWorkBook[Port].OlePropertyGet("Sheets", 1);

	// 表格的列数
	int nColCount(8);
	// 设置单元格的宽度
	for(int i=0; i<nColCount; i++)
    {
		int nColWidth = 28;
		m_vExcelApp[Port].OlePropertyGet("Columns", i + 1)
                .OlePropertySet("ColumnWidth", nColWidth / 2.6);
    }

	// 第一行写入测试相关信息
	m_vExcelApp[Port].OlePropertyGet("Rows", 1).OlePropertySet("RowHeight", 18);
	Variant Range1 = m_vSheet[Port].OlePropertyGet("Range","A1:D1");
	Range1.OleFunction("Merge",false);
	AnsiString Str = GetCurData().c_str();
	Str = "当前操作时间: "+Str;
	m_vSheet[Port].OlePropertyGet("Cells", 1, 1)
				.OlePropertySet("Value", Str.c_str());

	// 先将列名写入Excel表格
	const char* Name[18] = {"test"};
	for(int j=0; j<18; j++)
	{
		// 标题行的行高
		m_vExcelApp[Port].OlePropertyGet("Rows", 2).OlePropertySet("RowHeight", 15);
        // 写入标题
		m_vSheet[Port].OlePropertyGet("Cells", 2, j + 1)
                .OlePropertySet("Value",Name[j]);
		// 设置列名单元格的背景色
		Variant vInter = m_vSheet[Port].OlePropertyGet(
				"Cells", 2, j + 1).OlePropertyGet("Interior");
        vInter.OlePropertySet("ColorIndex", 15); // 灰色
        vInter.OlePropertySet("Pattern", 1); // xlSolid
        vInter.OlePropertySet("PatternColorIndex", -4105); // xlAutomatic
	}
}

//这个函数是每接到一包解析正确的数据后,就调用它保存数据
void TfrmMain::AddData(const int Port)
{
	//调试到这里的时候,就提示错误。
         //EOleSysError with message'因为应用程序正在发送一个输入同步呼叫,所以无法执行传出的呼叫'.
        int nRow = m_vSheet[Port].OlePropertyGet("UsedRange").OlePropertyGet("Rows")
				.OlePropertyGet("Count") + 1;

	int nCount = 1 + nRow;
	TListItem *Item = lvTable->Items->operator [](m_ItemIndex[t0]);
	if( NULL == Item ) return;
	AnsiString Caption = Item->Caption;
	m_vExcelApp[Port].OlePropertyGet("Rows", nCount).OlePropertySet("RowHeight", 16);
	m_vSheet[Port].OlePropertyGet("Cells", nCount, 1)
			.OlePropertySet("Value", Caption.c_str());
	for(int j=0; j<Item->SubItems->Count; j++)
	{
		AnsiString tmp = Item->SubItems->Strings[j];
		if( j == 0 ) tmp = "'" + tmp;
		m_vSheet[Port].OlePropertyGet("Cells", nCount, j + 2)
			.OlePropertySet("Value",tmp.c_str());
	}
}

//数据收发完毕后,关闭EXCEL,保存数据。
void TfrmMain::CloseExcelSave(const int Port)
{
        // 保存Excel文档并退出
	AnsiString filename = m_FileName;
	filename = filename.SubString(1,filename.Length()-4);
	filename = filename + "_" + IntToStr(Port);
	filename = filename + ".xls";
	m_vExcelApp[Port].OlePropertyGet("ActiveWorkbook")
			.OleFunction("SaveAs", filename.c_str());
	m_vWorkBook[Port].OleProcedure("Close");
	m_vExcelApp[Port].OleFunction("Quit");
	m_vSheet[Port] = Unassigned;
	m_vExcelApp[Port] = Unassigned;
	CoUninitialize();
}
真不知道问题在哪里了,麻烦大侠们给指点下迷津,同时也指导下调试方法,万分感谢。
sxqinge 2012-11-05
  • 打赏
  • 举报
回复
谢谢妖哥提示的思路,呵呵我感觉自己问的太多了,确实越来越觉得自己很菜了,基础太薄弱了点呵呵
ccrun.com 2012-11-05
  • 打赏
  • 举报
回复
引用 14 楼 sxqinge 的回复:
妖哥,我网上粗略的找了下资料,关于排队机制的不是很多,可以给个资料链接看看么?
没有什么资料,一个简单的实现方法就是:用自定义消息,需要写数据到Excel中的,就向某窗口发自定义消息,将要写的数据自己组合一下,通过参数传过去。然后窗口响应这个自定义消息,来调用AddData函数进行写操作。 注意,这个解决方案中,只能由某窗口响应消息自定义的地方才能调用AddData消息,其他地方不要调用。这样就是个简单的排队。
ccrun.com 2012-11-02
  • 打赏
  • 举报
回复
1. 创建Excel文件以前,先判断文件是否存在,如存在,直接打开。
2. 如果这个Excel对象在写完以后还要继续写,那就不要关闭它。
3. 如果新创建的文件保存时文件已存在,需要屏蔽掉Excel的警告提示:
vExcelApp.OlePropertySet("DisplayAlerts", false);
sxqinge 2012-11-02
  • 打赏
  • 举报
回复
我自己刚调试了下,发现m_vExcelApp的值在创建的时候假如有个值:001a45ec,因为创建后又把文件给关掉了,所以此时值变为-1;因此当在添加数据函数AddData中使用m_vExcelApp时就会发生类型不匹配的情况(应该如是吧?),这里我做了几个尝试:
1.在创建文件中不关闭文件,即将
m_vExcelApp.OleFunction("Quit");
m_vSheet = Unassigned;
m_vExcelApp = Unassigned;
这三条语句给屏蔽掉,发现在进入到添加函数,使用m_vExcelApp时又出现刚开始那样的错误“因为应用程序正在....”;
2.不屏蔽创建文件中的关闭语句,因为发现m_vExcelApp的值改变,因此将其设置为静态变量,提示错误发生意外,网上查找了下,说确保文件存在(经调试,很确定存在)。
本来我应该再自己想下的,但不想再多走弯路了,希望有人能替我解决,我自己再调试调试下,谢谢了
ccrun.com 2012-11-02
  • 打赏
  • 举报
回复
根据我摸索出来的经验,用OLE操作Office的过程中,涉及到字符串作为值的部分,建议用WideString类型。
如:

m_vExcelApp.OlePropertyGet("workbooks").OleFunction("open", WideString(filename));

你再试试。
sxqinge 2012-11-02
  • 打赏
  • 举报
回复
void AddData(AnsiString filename)
{
//这里设置断点后,提示Hr类型不匹配错误。
m_vExcelApp.OlePropertyGet("workbooks").OleFunction("open",filename.c_str());

......//数据添加代码
}

sxqinge 2012-11-02
  • 打赏
  • 举报
回复
妖哥,我还是得麻烦你了,按照你说的,我定义了一个全局的EXCEL对象。
variant m_vExcelApp,m_vSheet;
在Create函数里面基本不做变化,可以正常创建EXCEL表格。但是在添加数据时AddData()函数提示错误:hr:类型不匹配。
添加函数我分两部分:

void AddData(AnsiString filename)
{
//这里设置断点后,提示Hr类型不匹配错误。
m_vExcelApp[Port].OlePropertyGet("workbooks").OleFunction("open",filename.c_str());

int nRow = m_vSheet[Port].OlePropertyGet("UsedRange").OlePropertyGet("Rows")
.OlePropertyGet("Count") + 1;
......//数据添加代码
}

另外在存入过程结束后,我会调用关闭OLE函数:

Void CloseExcelSave()
{
m_vExcelAppOlePropertyGet("ActiveWorkbook").OleFunction("Save");
m_vExcelAppOlePropertySet("DisplayAlerts",false);
m_vExcelAppOleFunction("Quit");
m_vSheet = Unassigned;
m_vExcelApp = Unassigned;
}

请问下这到底哪里类型不匹配呢?
ccrun.com 2012-11-02
  • 打赏
  • 举报
回复
sxqinge 2012-11-02
  • 打赏
  • 举报
回复
首先恭喜妖哥升钻!!!
呵呵谢谢妖哥的回复,我改下程序试试
ccrun.com 2012-11-02
  • 打赏
  • 举报
回复
你这个思路不对。不要频繁的创建和销毁Excel对象,定义一个全局的Excel对象,开始的时候创建好,程序结束时保存文件并关闭。写数据时只针对这个Excel对象来就行了。

13,871

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧