【MFC/C++ 操作Excel】

【MFC/C++ 操作Excel】将数字格式单元格转为文本格式

       首先,请您先阅读 MFC操作office通用分析方法一篇,或者你需要了解本文的分析方法是按如下进行的:

1.       将我们的处理过程用宏记录下来

2.       将这一过程从VB翻译为VC

正文

当我们在用MFC操作excel时,为了操作的方便性,常常需要将数据转为文本格式来保存,这一过程怎样用C++来实现呢?

第一步:我们可以使用以下方法将文本转为文本格式:选中要转为文本格式的单元格,右键-》设置单元格格式-》文本-》确定。

 

第二步:上面这一过程用宏记录下来是这样的,下面选择的是从A5J64之间的单元格:

[vb] view plaincopy
 
  1. Range("A5:J64").Select  
  2.   
  3. Selection.NumberFormatLocal = "@"  


 

第三步:将上述VB转为VC实现:

//beginSendS之间的单元格转为文本格式存储

[cpp] view plaincopy
 
  1. BOOL SetTextFormat(CString beginS, CString endS)  
  2.   
  3. {  
  4.   
  5.        //注意,这里的m_ecSheet是_Worksheet的对象,你之前要先得到worksheet  
  6.   
  7. Range m_ecRange = m_ecSheet.GetRange(COleVariant(beginS), COleVariant(endS));  
  8.   
  9.        if(m_ecRange.m_lpDispatch)  
  10.   
  11.        {  
  12.   
  13.               //选择beginS, endS  
  14.   
  15.               m_ecRange.Select();  
  16.   
  17. //设置为文本格式  
  18.   
  19.               m_ecRange.SetNumberFormatLocal(COleVariant("@"));  
  20.   
  21.               return TRUE;  
  22.   
  23.        }  
  24.   
  25.        return FALSE;  
  26.   
  27. }  

调用方法:SetTextFormat(“A5”, “J64”)

       

       但是用上面的方法设置之后,原来是数字格式的单元格仍然不是文本格式,如果直接用VC操作会出错,这里有一种区分数字是否真正转为文本格式的方法:

下图左是按照上述方法设置后的结果,此时,数字仍然不是真正的文本,下图右则是真正的文本,它的特点是每个数字格左上角都有一个绿色的小三角。

 

那么如果将数字设置为真正的文本呢?我们按如下步骤进行。

第一步:手动设置方法

选中一列,按数据-》分列

 

直接按下一步

 

直接按下一步

 

这里要选择文本,红笔标出,然后按完成,此时,数字就变成真正的文本了。

第二步:上述过程用宏记录下来是这样的:

[vb] view plaincopy
 
  1. Range("A5:A64").Select  
  2.   
  3.     Selection.TextToColumns Destination:=Range("A5"), DataType:=xlDelimited, _  
  4.   
  5.         TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _  
  6.   
  7.         Semicolon:=False, Comma:=False, Space:=False, Other:=False, FieldInfo _  
  8.   
  9.         :=Array(1, 2), TrailingMinusNumbers:=True  

第三步:将其转为VC来实现

 

[cpp] view plaincopy
 
    1. _Worksheet m_ecSheet;//首先你要自己初始化哦!!!!  
    2.   
    3. Range m_ecRange;  
    4.   
    5. BOOL CExcelOperate::GetRangeAndValue(CString begin, CString end)  
    6.   
    7. {  
    8.   
    9.        if(!m_ecSheet.m_lpDispatch)  
    10.   
    11.        {  
    12.   
    13.               AfxMessageBox("Sheet获取失败!", MB_OK|MB_ICONWARNING);  
    14.   
    15.               return FALSE;  
    16.   
    17.        }  
    18.   
    19.        m_ecRange = m_ecSheet.GetRange(COleVariant(begin), COleVariant(end));  
    20.   
    21.        if(!m_ecRange.m_lpDispatch)  
    22.   
    23.        {  
    24.   
    25.               AfxMessageBox("Range获取失败!", MB_OK|MB_ICONWARNING);  
    26.   
    27.               return FALSE;  
    28.   
    29.        }  
    30.   
    31.        ret = m_ecRange.GetValue2();//得到表格中的值  
    32.   
    33.        return TRUE;  
    34.   
    35. }  
    36.   
    37. BOOL CExcelOperate::SetRowToTextFormat(CString &beginS, CString &endS)  
    38.   
    39. {  
    40.   
    41.        if(GetRangeAndValue(beginS, endS))  
    42.   
    43.        {  
    44.   
    45.               m_ecRange.Select();  
    46.   
    47.               Range m_tempRange = m_ecSheet.GetRange(COleVariant(beginS), COleVariant(beginS));  
    48.   
    49.               if(!m_tempRange.m_lpDispatch) return FALSE;  
    50.   
    51.               COleVariant vTrue((short)TRUE),      
    52.   
    53.                 vFalse((short)FALSE);  
    54.   
    55.               int tempArray[2] = {1, 2};  
    56.   
    57.               COleSafeArray saRet;  
    58.   
    59.               DWORD numElements = {2};  
    60.   
    61.               saRet.Create(VT_I4, 1, &numElements);  
    62.   
    63.               long index = 0;  
    64.   
    65.               int val = 1;  
    66.   
    67.               saRet.PutElement(&index, &val);  
    68.   
    69.               index++;  
    70.   
    71.               val = 2;  
    72.   
    73.               saRet.PutElement(&index, &val);  
    74.   
    75.               //m_tempRange.GetItem(COleVariant((short)5),COleVariant("A"));  
    76.   
    77.               m_ecRange.TextToColumns(m_tempRange.GetItem(COleVariant((short)1),COleVariant((short)1)), 1, 1, vFalse, vTrue, vFalse, vFalse, vFalse, vFalse, vFalse, saRet, vFalse, vFalse, vTrue);  
    78.   
    79.               m_tempRange.ReleaseDispatch();  
    80.   
    81.               return TRUE;  
    82.   
    83.        }  
    84.   
    85.        return FALSE;  
    86.   
    87. }  

【MFC/C++ 操作Excel】C++下TextToColumns函数的参数

我们在使用excel的分列将数字转为文本时,用宏记录的vb代码如下:

[vb] view plaincopy
 
  1. Range("A5:A64").Select  
  2.     Selection.TextToColumns Destination:=Range("A5"), DataType:=xlDelimited, _  
  3.         TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _  
  4.         Semicolon:=False, Comma:=False, Space:=False, Other:=False, FieldInfo _  
  5.         :=Array(1, 2), TrailingMinusNumbers:=True  


如果我们想将其转为VC代码,过程如下:

第一句:

[vb] view plaincopy
 
  1. Range("A5:A64").Select  

这一句表示选中A5:A64,翻译为C++,就是

[cpp] view plaincopy
 
  1. m_ecRange.Select();  

其中m_ecRange是Range的对象。

第二句:

[vb] view plaincopy
 
  1. Selection.TextToColumns Destination:=Range("A5"), DataType:=xlDelimited, _ TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _ Semicolon:=False, Comma:=False, Space:=False, Other:=False, FieldInfo _ :=Array(1, 2), TrailingMinusNumbers:=True  

其对应的是Range类的TextToColumns函数,其C++函数原型是

[cpp] view plaincopy
 
  1. VARIANT TextToColumns(const VARIANT& Destination, long DataType, long TextQualifier, const VARIANT& ConsecutiveDelimiter, const VARIANT& Tab, const VARIANT& Semicolon, const VARIANT& Comma, const VARIANT& Space, const VARIANT& Other,   
  2.   const VARIANT& OtherChar, const VARIANT& FieldInfo, const VARIANT& DecimalSeparator, const VARIANT& ThousandsSeparator, const VARIANT& TrailingMinusNumbers);  


各个参数的意思可以参见:

http://bbs.csdn.net/topics/390285992

这里的参数只有第1个const VARIANT& Destination和第11个const VARIANT& FieldInfo比较难确定,其他参数都可以通过在宏中用MsgBox得到,下面说明这两个参数:

第1个参数(const VARIANT& Destination):

MSDN解释:指定 Microsoft Excel 放置结果的位置的 Range 对象。如果该区域大于一个单元格,请使用左上角的单元格。

所以这里我们设置为A5单元格,我们可以使用:

[cpp] view plaincopy
 
  1. CString beginS = “A5”;//将beginS设置为这一列左上角的单元格  
  2.   
  3. Range m_tempRange = m_ecSheet.GetRange(COleVariant(beginS), COleVariant(beginS));//得到该单元格的range  
  4.   
  5. m_tempRange.GetItem(COleVariant((short)1),COleVariant((short)1));//返回的值就是要传入的值,也就是左上角单元格,这里一定是1,1,因为range只有一个单元格  


 

第11个参数(const VARIANT& FieldInfo)

MSDN解释:包含单列数据拆分信息的数组。对本参数的解释取决于 DataType 的值。如果此数据由分隔符分隔,则本参数为由两元素数组组成的数组,其中每个两元素数组指定一个特定列的转换选项。第一个元素为列标(从 1 开始),第二个元素是 xlColumnDataType 常量之一,用以指定该列的拆分方式。
我们可以看到VB代码是Array(1, 2),是一个一维数组,数组有2个元素,数组的第一个元素是1,第二个元素是2;在MFC中,我们要使用
COleSafeArray来代表数组,初始化这样一个数组如下:

[cpp] view plaincopy
 
  1. COleSafeArray saRet;  
  2. DWORD numElements = {2};//数组中有2个元素  
  3. saRet.Create(VT_I4, 1, &numElements);//第一个参数表示存入int,第二个参数表示是一维数组,第三个参数表示数组中有2个元素  
  4. long index = 0;//数组下标  
  5. int val = 1;//值  
  6. saRet.PutElement(&index, &val);//将0下标的值设置为1  
[cpp] view plaincopy
 
  1. index++;  
  2. val = 2;  
  3. saRet.PutElement(&index, &val);//将1下标的值设置为2<p> </p>  


整个函数如下:

[cpp] view plaincopy
 
  1. BOOL CExcelOperate::SetRowToTextFormat(CString &beginS, CString &endS)  
  2. {  
  3.     if(GetRangeAndValue(beginS, endS))  
  4.     {  
  5.         m_ecRange.Select();  
  6.         Range m_tempRange = m_ecSheet.GetRange(COleVariant(beginS), COleVariant(beginS));  
  7.         if(!m_tempRange.m_lpDispatch) return FALSE;  
  8.         COleVariant vTrue((short)TRUE),      
  9.                 vFalse((short)FALSE);  
  10.         //int tempArray[2] = {1, 2};  
  11.         COleSafeArray saRet;  
  12.         DWORD numElements = {2};  
  13.         saRet.Create(VT_I4, 1, &numElements);  
  14.         long index = 0;  
  15.         int val = 1;  
  16.         saRet.PutElement(&index, &val);  
  17.         index++;  
  18.         val = 2;  
  19.         saRet.PutElement(&index, &val);  
  20.         //m_tempRange.GetItem(COleVariant((short)5),COleVariant("A"));  
  21.         m_ecRange.TextToColumns(m_tempRange.GetItem(COleVariant((short)1),COleVariant((short)1)), 1, 1, vFalse, vTrue, vFalse, vFalse, vFalse, vFalse, vFalse, saRet, vFalse, vFalse, vTrue);  
  22.         m_tempRange.ReleaseDispatch();  
  23.         return TRUE;  
  24.     }  
  25.     return FALSE;  
  26. }  


 

[cpp] view plaincopy
 
    1. BOOL CExcelOperate::GetRangeAndValue(CString begin, CString end)  
    2. {  
    3.     if(!m_ecSheet.m_lpDispatch)  
    4.     {  
    5.         AfxMessageBox("Sheet获取失败!", MB_OK|MB_ICONWARNING);  
    6.         return FALSE;  
    7.     }  
    8.     m_ecRange = m_ecSheet.GetRange(COleVariant(begin), COleVariant(end));  
    9.     if(!m_ecRange.m_lpDispatch)  
    10.     {  
    11.         AfxMessageBox("Range获取失败!", MB_OK|MB_ICONWARNING);  
    12.         return FALSE;  
    13.     }  
    14.     ret = m_ecRange.GetValue2();//得到表格中的值  
    15.     return TRUE;  
    16. }  
原文地址:https://www.cnblogs.com/For-her/p/3499881.html