여러 군대 찾아도 정보가 미흡하여, 사용 가능하게 정리하였습니다.
- XLEzAutomation이나 ExcelLib의 기능에 원하는 기능 구현이 없고 수정 추가에도 어려움이 있어서...
- 잘 활용하시기 바랍니다.
Excel 컨트롤 클래스 만들기.
(필요할 때마다 하나씩 추가 하자~~~~)
구현 기능
1 파일 열기,
2 파일 닫기,
3 다른이름 저장,
4 값 일기,
5 값 쓰기,
6 이미지 저장하기(클립보드, 절대 경로 Link, Link를 이용한 포함시키기)
7 Sheet Active 시키기.
미구현 기능
8 차트 만들기.
9 Sheet이름 바꾸기.
10 범용 알고리즘 콜하기.
추가된 Excel File들은 복사하여 다른 프로젝트에 Link를 걸고 그대로 사용 가능하다.
(MFC에서 Excel 컨트롤 하기(1)을 매 프로젝트에 추가할 필요는 없다)
#include "CApplication.h"//
#include "CWorkbook.h"//
#include "CWorkbooks.h"//
#include "CWorksheet.h"//
#include "CWorksheets.h"//
#include "CChart.h"//
#include "CCharts.h"//
#include "CBorder.h"//
#include "CBorders.h"//
#include "CPicture.h"//
#include "CPictures.h"//
#include "CRange.h"//
#include "CFont0.h"//
#include "CShapes.h"
#include "CShape.h"
구현 해더 파일.(ExcelCtrl.h)
#pragma once
#include "CApplication.h"//
#include "CWorkbook.h"//
#include "CWorkbooks.h"//
#include "CWorksheet.h"//
#include "CWorksheets.h"//
#include "CChart.h"//
#include "CCharts.h"//
#include "CBorder.h"//
#include "CBorders.h"//
#include "CPicture.h"//
#include "CPictures.h"//
#include "CRange.h"//
#include "CFont0.h"//
#include "CShapes.h"
#include "CShape.h"
static CString ColToColLetter(int colIndex)
{
int div = colIndex;
CString colLetter;// = String.Empty;
int mod = 0;
while (div > 0)
{
mod = (div - 1) % 26;
colLetter = (char)(65 + mod) + colLetter;
div = (int)((div - mod) / 26);
}
return colLetter;
}
static int ColLetterToColIndex(CString columnLetter)
{
columnLetter = columnLetter.MakeUpper();
int sum = 0;
for (int i = 0; i < columnLetter.GetLength(); i++)
{
sum *= 26;
sum += (columnLetter[i] - L'A' + 1);
}
return sum;
}
class CExcelCtrl
{
public:
CExcelCtrl();
~CExcelCtrl();
private:
// spreadsheet variables
CApplication m_app;
CWorkbook m_book;
CWorkbooks m_books;
CWorksheets m_worksheets;
COleVariant m_covTrue;
COleVariant m_covFalse;
COleVariant m_covOptional;
CString m_strOpenFile;
private:
void CloseWorkbook();
public:
//1) File 열고 닫기.
bool OpenFile(CString strFilePath);
bool CloseFile();
bool SaveFile();
bool SaveAsFile(CString newFullPath);
//2) Data 읽고 쓰기.
CString GetValue(int nSheet, CString strCellPos);//CellPos :"A1", "O21"
void SetValue(int nSheet, CString strCellPos, CString strNewValue);
//3) Image 삽입.
void SetPasteClipboard(int nSheet, CString strCellPos, double fViewSizeW = 0.0, double fViewSizeH = 0.0);//클립 보드의 이미지 삽입
void SetPasteFileLink(int nSheet, CString strCellPos, CString strImgPath, double fViewSizeW = 0.0, double fViewSizeH = 0.0);//주어진 이미지 절대 경로를 삽입.(경로만)
void SetFileLinkAndAdd(int nSheet, CString strCellPos, CString strImgPath, int orgW, int orgH, double fViewSizeW = 0.0, double fViewSizeH = 0.0);//경로의 파일을 삽입.(Excel File에 첨부)
void SetActiveSheet(int nSheet);
};
구현 소스파일(ExcelCtrl.cpp)
#include "stdafx.h"
#include "ExcelCtrl.h"
#define rmm 23
CExcelCtrl::CExcelCtrl():
m_app(nullptr),
m_book(nullptr),
m_books(nullptr),
m_covTrue((short)TRUE),
m_covFalse((short)TRUE),
m_covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR)
{
try
{
OleUninitialize(); //프로젝트 내 다른 COM이 초기화해 놓은 것을 죽여 놓으
DWORD dwOleVer;
dwOleVer = CoBuildVersion();
// check the OLE library version
if (rmm != HIWORD(dwOleVer))
{
MessageBox(NULL, _T("Incorrect version of OLE libraries."), L"Failed", MB_OK | MB_ICONSTOP);
return;
}
// could also check for minor version, but this application is
// not sensitive to the minor version of OLE
// initialize OLE, fail application if we can't get OLE to init.
if (FAILED(OleInitialize(NULL)))
{
MessageBox(NULL, _T("Cannot initialize OLE."), L"Failed", MB_OK | MB_ICONSTOP);
return;
}
if (!m_app.CreateDispatch(L"Excel.Application"))
{
AfxMessageBox(L"Could not start Excel.");
return;
}
m_app.put_DisplayAlerts(VARIANT_FALSE);
m_app.put_UserControl(FALSE);
}
catch (CMemoryException* e)
{
CMemoryException* ep = e;
AfxMessageBox(L"CMemoryException Could not clean up workbook.");
}
catch (CFileException* e)
{
CFileException* pe = e;
AfxMessageBox(L"CFileException Could not clean up workbook.");
}
catch (CException* e)
{
CException* pe = e;
AfxMessageBox(L"CException Could not clean up workbook.");
}
}
CExcelCtrl::~CExcelCtrl()
{
CloseFile();
OleUninitialize();
OleInitialize(NULL); //프로젝트 내 다른 COM을 위한 센스
}
bool CExcelCtrl::OpenFile(CString strFilePath)
{
m_strOpenFile.Format(L"%s", strFilePath);
// close already-opened workbook
CloseWorkbook();
bool retV = false;
try
{
// Get Workbooks collection.
LPDISPATCH lpDisp;
lpDisp = m_app.get_Workbooks(); // Get an IDispatch pointer
ASSERT(lpDisp);
m_books.AttachDispatch(lpDisp); // Attach the IDispatch pointer to the books object.
// open the document
lpDisp = m_books.Open(m_strOpenFile.GetBuffer(m_strOpenFile.GetLength()),
m_covOptional, m_covOptional, m_covOptional, m_covOptional,
m_covOptional, m_covOptional, m_covOptional, m_covOptional,
m_covOptional, m_covOptional, m_covOptional, m_covOptional,
m_covOptional, m_covOptional);
ASSERT(lpDisp);
//Set CWorkbook to use lpDisp, the IDispatch* of the actual workbook.
m_book.AttachDispatch(lpDisp);
//WorkSheets Link.
m_worksheets = m_book.get_Sheets();
retV = true;
}
catch (CMemoryException* e)
{
CMemoryException* ep = e;
AfxMessageBox(L"CMemoryException Could not clean up workbook.");
}
catch (CFileException* e)
{
CFileException* pe = e;
AfxMessageBox(L"CFileException Could not clean up workbook.");
}
catch (CException* e)
{
CException* pe = e;
AfxMessageBox(L"CException Could not clean up workbook.");
}
return retV;
}
bool CExcelCtrl::CloseFile()
{
bool retV = false;
CloseWorkbook();
try
{
m_app.Quit();
m_app.ReleaseDispatch();
retV = true;
}
catch (CMemoryException* e)
{
CMemoryException* ep = e;
AfxMessageBox(L"CMemoryException Could not clean up workbook.");
}
catch (CFileException* e)
{
CFileException* pe = e;
AfxMessageBox(L"CFileException Could not clean up workbook.");
}
catch (CException* e)
{
CException* pe = e;
AfxMessageBox(L"CException Could not clean up workbook.");
}
return retV;
}
bool CExcelCtrl::SaveFile()
{
bool retV = false;
if (m_app == nullptr || m_books == nullptr || m_book == nullptr)
return retV;
try
{
m_book.Save();
retV = true;
}
catch (CMemoryException* e)
{
CMemoryException* ep = e;
AfxMessageBox(L"CMemoryException Could not clean up workbook.");
}
catch (CFileException* e)
{
CFileException* pe = e;
AfxMessageBox(L"CFileException Could not clean up workbook.");
}
catch (CException* e)
{
CException* pe = e;
AfxMessageBox(L"CException Could not clean up workbook.");
}
return retV;
}
bool CExcelCtrl::SaveAsFile(CString newFullPath)
{
bool retV = false;
if (m_app == nullptr || m_books == nullptr || m_book == nullptr)
return false;
try
{
//51 = xlOpenXMLWorkbook(without macro's in 2007-2016, xlsx)
//52 = xlOpenXMLWorkbookMacroEnabled(with or without macro's in 2007-2016, xlsm)
//50 = xlExcel12(Excel Binary Workbook in 2007 - 2016 with or without macro's,xlsb)
//56 = xlExcel8(97 - 2003 format in Excel 2007 - 2016, xls)
int nPos = newFullPath.ReverseFind(L'.');
CString strExeName;
strExeName.Format(L"%s", newFullPath.Mid(nPos+1));
//strExeName.MakeUpper();
long nFileCode = 51;
if (strExeName.CompareNoCase(L"xlsm") == 0)
nFileCode = 52;
m_book.SaveAs(
COleVariant(newFullPath.GetBuffer(newFullPath.GetLength())),
COleVariant(nFileCode),//file format
m_covOptional,//COleVariant(_T(""), // password
m_covOptional,//COleVariant(_T(""), VT_BSTR), //readonly
m_covOptional,//covFalse,
//createbackup
m_covOptional,//covFalse,
//accessmode
1,
m_covOptional,//COleVariant((long) 1),
m_covOptional,
m_covOptional,
m_covOptional, m_covOptional);
retV = true;
}
catch (CMemoryException* e)
{
CMemoryException* ep = e;
AfxMessageBox(L"CMemoryException Could not clean up workbook.");
}
catch (CFileException* e)
{
CFileException* pe = e;
AfxMessageBox(L"CFileException Could not clean up workbook.");
}
catch (CException* e)
{
CException* pe = e;
AfxMessageBox(L"CException Could not clean up workbook.");
}
return retV;
}
void CExcelCtrl::CloseWorkbook()
{
try
{
m_worksheets.ReleaseDispatch();
// close already-opened workbook
m_book.ReleaseDispatch();
m_books.Close();
m_books.ReleaseDispatch();
}
catch (CMemoryException* e)
{
CMemoryException* ep = e;
AfxMessageBox(L"CMemoryException Could not clean up workbook.");
}
catch (CFileException* e)
{
CFileException* pe = e;
AfxMessageBox(L"CFileException Could not clean up workbook.");
}
catch (CException* e)
{
CException* pe = e;
AfxMessageBox(L"CException Could not clean up workbook.");
}
}
CString CExcelCtrl::GetValue(int nSheet, CString strCellPos)
{
if (nSheet < 1 || m_app == nullptr)
return CString(L"");
CString szValue;
try
{
// sheet 생성, 연결 (1번 시트)
CWorksheet sheet;
sheet = m_worksheets.get_Item(COleVariant((short)nSheet));
sheet.Activate();
// range 생성, 연결
CRange range;
range.AttachDispatch(sheet.get_Cells(), true);
range = sheet.get_Range(COleVariant(strCellPos.GetBuffer(strCellPos.GetAllocLength())), m_covOptional);
range.Select();
//------------------------------------------------------
COleVariant vargValue = range.get_Value2();
switch (vargValue.vt)
{
case VT_UI1:
{
unsigned char nChr = vargValue.bVal;
//szValue = nChr;
szValue.Format(L"%d", nChr);// = nChr;
}
break;
case VT_I4:
{
long nVal = vargValue.lVal;
szValue.Format(L"%i", nVal);
}
break;
case VT_R4:
{
float fVal = vargValue.fltVal;
szValue.Format(L"%f", fVal);
}
break;
case VT_R8:
{
double dVal = vargValue.dblVal;
szValue.Format(L"%f", dVal);
}
break;
case VT_BSTR:
{
BSTR b = vargValue.bstrVal;
szValue = b;
}
break;
case VT_BYREF | VT_UI1:
{
//Not tested
unsigned char* pChr = vargValue.pbVal;
// szValue = *pChr;
szValue.Format(L"%f", *pChr);
}
break;
case VT_BYREF | VT_BSTR:
{
//Not tested
BSTR* pb = vargValue.pbstrVal;
szValue = *pb;
}
case 0:
{
//Empty
szValue = _T("");
}
break;
}
//------------------------------------------------------
range.ReleaseDispatch();
sheet.ReleaseDispatch();
}
catch (CMemoryException* e)
{
CMemoryException* ep = e;
AfxMessageBox(L"CMemoryException Could not clean up workbook.");
}
catch (CFileException* e)
{
CFileException* pe = e;
AfxMessageBox(L"CFileException Could not clean up workbook.");
}
catch (CException* e)
{
CException* pe = e;
AfxMessageBox(L"CException Could not clean up workbook.");
}
return szValue;
}
void CExcelCtrl::SetValue(int nSheet, CString strCellPos, CString strNewValue)
{
if (nSheet < 1 || m_app == nullptr)
return;
try
{
// sheet 생성, 연결 (1번 시트)
CWorksheet sheet;
sheet = m_worksheets.get_Item(COleVariant((short)nSheet));
sheet.Activate();
// range 생성, 연결
CRange range;
range.AttachDispatch(sheet.get_Cells(), true);
range = sheet.get_Range(COleVariant(strCellPos.GetBuffer(strCellPos.GetAllocLength())), m_covOptional);
range.Select();
//------------------------------------------------------
//Data 쓰기.
range.put_Value2(COleVariant(strNewValue));
//------------------------------------------------------
range.ReleaseDispatch();
sheet.ReleaseDispatch();
}
catch (CMemoryException* e)
{
CMemoryException* ep = e;
AfxMessageBox(L"CMemoryException Could not clean up workbook.");
}
catch (CFileException* e)
{
CFileException* pe = e;
AfxMessageBox(L"CFileException Could not clean up workbook.");
}
catch (CException* e)
{
CException* pe = e;
AfxMessageBox(L"CException Could not clean up workbook.");
}
}
void CExcelCtrl::SetActiveSheet(int nSheet)
{
if (nSheet < 1 || m_app == nullptr)
return;
CWorksheet sheet;
sheet = m_worksheets.get_Item(COleVariant((short)nSheet));
sheet.Activate();
}
void CExcelCtrl::SetPasteClipboard(int nSheet, CString strCellPos, double fViewSizeW , double fViewSizeH)
{
if (nSheet < 1 || m_app == nullptr)
return;
CWorksheet sheet;
CRange range;
CPicture pic;
CPictures pics;
//CBorder border;
sheet = m_worksheets.get_Item(COleVariant((short)nSheet));
pics = sheet.Pictures(m_covOptional);
sheet.Activate();
// insert first picture and put a border on it
range = sheet.get_Range(COleVariant(strCellPos.GetBuffer(strCellPos.GetAllocLength())), m_covOptional);
range.Select();
//링크 집어넣기
//pic = pics.Insert(strLoadImgPath.GetBuffer(strLoadImgPath.GetLength()), covOptional);
//붙여넣기
sheet.Activate();
pic = pics.Paste(m_covOptional);
VARIANT varL = range.get_Left();
VARIANT varT = range.get_Top();
VARIANT varW = range.get_Width();
VARIANT varH = range.get_Height();
double l = varL.dblVal + 2.0;
double t = varT.dblVal + 2.0;
double w = varW.dblVal;
double h = varH.dblVal;
//Sheet 에서 위치 지정.
pic.put_Left(l);
pic.put_Top(t);
pic.put_Locked(FALSE);
//크기 지정.
if (fViewSizeW > 0.0 )//&& fViewSizeH > 0.0)
{
pic.put_Width(fViewSizeW);
//pic.put_Height(fViewSizeW);
}
pic.put_Visible(TRUE);
//VARIANT Replace;
//pic.Select(Replace);
//m_book.Save();
pic.ReleaseDispatch();
pics.ReleaseDispatch();
range.ReleaseDispatch();
sheet.ReleaseDispatch();
}
void CExcelCtrl::SetPasteFileLink(int nSheet, CString strCellPos, CString strImgPath, double fViewSizeW, double fViewSizeH)
{
if (nSheet < 1 || m_app == nullptr || strImgPath.GetLength()<3)
return;
CWorksheet sheet;
CRange range;
CPicture pic;
CPictures pics;
//CBorder border;
sheet = m_worksheets.get_Item(COleVariant((short)nSheet));
sheet.Activate();
pics = sheet.Pictures(m_covOptional);
// insert first picture and put a border on it
// 링크 집어넣기
range = sheet.get_Range(COleVariant(strCellPos.GetBuffer(strCellPos.GetAllocLength())), m_covOptional);
range.Select();
VARIANT varL = range.get_Left();
VARIANT varT = range.get_Top();
VARIANT varW = range.get_Width();
VARIANT varH = range.get_Height();
double l = varL.dblVal + 2.0;
double t = varT.dblVal + 2.0;
double w = varW.dblVal;
double h = varH.dblVal;
sheet.Activate();
pic = pics.Insert(strImgPath.GetBuffer(strImgPath.GetLength()), m_covOptional);
//붙여넣기
//range = sheet.get_Range(COleVariant(strCellPos.GetBuffer(strCellPos.GetAllocLength())), m_covOptional);
//range.Select();
//pic = pics.Paste(m_covOptional);
//Sheet 에서 위치 지정.
pic.put_Left(l);
pic.put_Top(t);
//크기 지정.
if (fViewSizeW > 0.0)//&& fViewSizeH > 0.0)
{
pic.put_Width(fViewSizeW);
//pic.put_Height(fViewSizeW);
}
pic.ReleaseDispatch();
pics.ReleaseDispatch();
//m_book.Save();
range.ReleaseDispatch();
sheet.ReleaseDispatch();
}
void CExcelCtrl::SetFileLinkAndAdd(int nSheet, CString strCellPos, CString strImgPath, int orgW, int orgH, double fViewSizeW, double fViewSizeH)
{
if (nSheet < 1 || m_app == nullptr || strImgPath.GetLength() < 3)
return;
CWorksheet sheet;
CRange range;
CPicture pic;
CPictures pics;
//CBorder border;
sheet = m_worksheets.get_Item(COleVariant((short)nSheet));
sheet.Activate();
range = sheet.get_Range(COleVariant(strCellPos.GetBuffer(strCellPos.GetAllocLength())), m_covOptional);
range.Select();
VARIANT varL = range.get_Left();
VARIANT varT = range.get_Top();
VARIANT varW = range.get_Width();
VARIANT varH = range.get_Height();
double l = varL.dblVal + 2.0;
double t = varT.dblVal + 2.0;
double w = varW.dblVal;
double h = varH.dblVal;
CShapes objShapes;
CShape objShape;
objShapes = sheet.get_Shapes();
objShape = objShapes.AddPicture(strImgPath, // Filename
(long)0, // LinkToFile
(long)-1, // SaveWithDocument
(float)l, // Left
(float)t, // Top
(float)orgW, // Width
(float)orgH); // Height
if (fViewSizeW > 0.0 && fViewSizeH > 0.0)
{
objShape.put_Width((float)fViewSizeW);
objShape.put_Height((float)fViewSizeH);
}
if (objShapes.m_lpDispatch)
objShapes.ReleaseDispatch();
if (objShape.m_lpDispatch)
objShape.ReleaseDispatch();
range.ReleaseDispatch();
sheet.ReleaseDispatch();
}
'작업 > MFC' 카테고리의 다른 글
MFC OpneMP 간단 사용하기. (1) | 2020.03.10 |
---|---|
MFC Tip : CTime 시간 설정, TRACE() 찍기 오류 상황. (0) | 2020.03.10 |
MFC에서 Excel 컨트롤 하기(1) (0) | 2020.01.23 |
EXE 관리자 권한으로 System폴더의 ini접근을 위해 (0) | 2019.12.16 |
Thread - Mutual Exclusion : 상호 배제 (0) | 2019.11.29 |