网上有很多C++利用OLE读取Excel的例子,其中有提到利用COleSafeArray类来预加载数据来提升效率,但是没有实现快速的写入大量数据到Excel,今天专门写了一个方法,同样利用COleSafeArray类将大量数据一次性的写入Excel,提高了效率,参考代码如下:

void CExcelFile::SetString(long startRow, long startCol, long RowCount, long
ColCount, vector< vector<CComBSTR> >& writeData)
{
    if (startRow < 1 || startCol < 1)
    {
        return;
    }

    VARTYPE vt = VT_BSTR; /*数组元素的类型,string*/
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
    sabWrite[0].cElements = RowCount;
    sabWrite[0].lLbound = 0;
    sabWrite[1].cElements = ColCount;
    sabWrite[1].lLbound = 0;

    COleSafeArray olesaWrite;
    olesaWrite.Create(vt, sizeof(sabWrite) / sizeof(SAFEARRAYBOUND),
sabWrite);
    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
    long(*pArray)[2] = NULL;
    olesaWrite.AccessData((void **)&pArray);
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements *
sizeof(long));
    /*释放指向数组的指针*/
    olesaWrite.UnaccessData();
    pArray = NULL;

    /*对二维数组的元素进行逐个赋值*/
    long index[2] = { 0, 0 };
    long lFirstLBound = 0;
    long lFirstUBound = 0;
    long lSecondLBound = 0;
    long lSecondUBound = 0;
    olesaWrite.GetLBound(1, &lFirstLBound);
    olesaWrite.GetUBound(1, &lFirstUBound);
    olesaWrite.GetLBound(2, &lSecondLBound);
    olesaWrite.GetUBound(2, &lSecondUBound);
    for (long i = lFirstLBound; i <= lFirstUBound; i++)
    {
        index[0] = i;
        for (long j = lSecondLBound; j <= lSecondUBound; j++)
        {
            index[1] = j;
            
            //防止越界而且不写入空值
            if ((i < writeData.size()) && (j < writeData[i].size()) &&
(writeData[i][j].Length() != 0))
            {
                olesaWrite.PutElement(index, (void*)writeData[i][j]);
            }
        }
    }
    
    CString strStartRow;
    CString strStartCol;
    strStartRow.Format(_T("%d"), startRow);
    strStartCol = ConvertNumColtoStringCol(startCol);
    CString strRange1;
    strRange1 = strStartCol + strStartRow;
    
    CString strEndRow;
    CString strEndCol;
    strEndRow.Format(_T("%d"), startRow + RowCount - 1);
    strEndCol = ConvertNumColtoStringCol(startCol + ColCount - 1);
    CString strRange2;
    strRange2 = strEndCol + strEndRow;
    ///
    CRange start_range = excel_work_sheet_.get_Range(COleVariant(strRange1),
COleVariant(strRange2));
    start_range.put_Value2((VARIANT)olesaWrite);
    start_range.ReleaseDispatch();
}

//将Excel数字列转为字符串列,1--A
CString CExcelFile::ConvertNumColtoStringCol(long Col)
{
    CString strBack;
    do {
        Col--;
        int n = Col % 26;
        CString strTemp;
        strTemp.Format(_T("%c"), n + (int) 'A');
        strBack += strTemp;
        Col = (int)((Col - n) / 26);
    } while (Col > 0);
    return strBack;
}

需要注意的地方是,字符串必须要要BSTR类型,不然会提示内存不足,我这里用的是CComBSTR。

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信