#pragma once #ifdef EARTHWORM_EXPORT #define DLLIMPEXP __declspec(dllexport) #else #define DLLIMPEXP __declspec(dllimport) #endif #include "dbtable.h" #include "dbTableStyle.h " #include class DLLIMPEXP MKTABLE { public: typedef std::vector RowData; typedef std::vector TableData; public: // 查找 AcDbTableStyle ,不存在则创建默认样式 static AcDbObjectId getTableStyle(LPCTSTR pszTSName); // 查找 AcDbTextStyleTableRecord ,不存在则创建默认样式 static AcDbObjectId getTextStyle(LPCTSTR pszTSName); // 查找 AcDbLinetypeTableRecord ,不存在则创建默认样式 static AcDbObjectId getLinetype(LPCTSTR pszLinetypeName); // 取 listCtrl 中 idxs 指定的列,按顺序提取数据 static bool extractDatasFromListCtrl(CListCtrl &listCtrl , std::vector &outDatas , RowData &headers , const std::vector &idxs , const int &maxRow); // 通过界面选择 listCtrl 中的列,并返回所选列的索引,包含顺序 static void selectColumnsFromListCtrl(CHeaderCtrl &headerCtrl , std::vector &idxs , double &dPScale , CString &sTemplate); // 自动根据表格内容调整表格大小 static void autoSizeTable(AcDbTable *pTable); // 获得表格模板列表 static void getTableTemplateList(std::vector &outTemplates); public: // 针对数据保存在CListCtrl中的表格,生成 AcDbTable static bool makeTable(CListCtrl &listCtrl, LPCTSTR pszTitle, const int &maxRow); }; #define _DEFINE_(type, name)\ void set##name(const type &val)\ {\ m_##name = val;\ m_bUse##name = true;\ }\ type m_##name;\ bool m_bUse##name #define _DEFINE_LINETYPE_PROPERTY_(name, linetype)\ void set##name(const CellGridLineTypeProperty &val)\ {\ m_##name = val;\ m_bUse##name = true;\ }\ CellGridLineTypeProperty m_##name;\ bool m_bUse##name #define APPLY_MARGIN(v)\ if (m_bUse##v)\ {\ pTS->setMargin(AcDb::kCellMargin##v, m_##v*dPScale, pszCellStyle);\ } #define APPLY_GRIDLINE_PROPERTY(v)\ if (m_bUse##v)\ {\ pTb->setGrid##v(nRow, nCol, m_type, m_##v);\ } #define APPLY_GRIDLINE_TYPE(v)\ for (size_t i = 0; i < m_##v.size(); ++i)\ {\ m_##v[i].apply2Table(pTb);\ }\ #define APPLY_CELL_STYLE(v)\ if (m_bUse##v)\ {\ pTS->set##v(m_##v, m_sName);\ } class MKTABLE; namespace TABLE { struct CellMergeRange { int m_maxRow, m_minRow, m_maxCol, m_minCol; CellMergeRange(): m_maxRow(-1), m_minRow(-1), m_maxCol(-1), m_minCol(-1) {} CellMergeRange(const CellMergeRange &mg): m_maxRow(mg.m_maxRow) , m_minRow(mg.m_minRow) , m_maxCol(mg.m_maxCol) , m_minCol(mg.m_minCol) { } CellMergeRange(const int &minRow , const int &maxRow , const int &minCol , const int &maxCol) : m_maxRow(maxRow) , m_minRow(minRow) , m_maxCol(maxCol) , m_minCol(minCol) { } CellMergeRange& operator=(const CellMergeRange &mg) { if (this != &mg) { m_maxRow = mg.m_maxRow; m_minRow = mg.m_minRow; m_maxCol = mg.m_maxCol; m_minCol = mg.m_minCol; } return *this; } bool vaild(const int &nRow, const int &nCol) { // 负数表示从后往前计数,先计算正确位置 if (m_minRow < 0) m_minRow += nRow; if (m_maxRow < 0) m_maxRow += nRow; if (m_minCol < 0) m_minCol += nCol; if (m_maxCol < 0) m_maxCol += nCol; // 边缘保护调整 // 最小行/列 小于0,调整为0,即第一行 if (m_minRow < 0) m_minRow = 0; if (m_minCol < 0) m_minCol = 0; // 最大行/列 大于总行/列数,调整为总行/列数-1,即最后一行 if (m_maxRow >= nRow) m_maxRow = nRow - 1; if (m_maxCol >= nRow) m_maxCol = nCol - 1; // 最小行/列大于总行/列数 if (m_minRow > nRow || m_minCol > nCol) return false; // 最大行/列 小于0 if (m_maxRow < 0 || m_maxCol < 0) return false; // 最小行/列 大于 最大行/列 if (m_minRow > m_maxRow || m_minCol > m_maxCol) return false; return true; } void apply2Table(AcDbTable *pTb) { if (vaild(pTb->numRows(), pTb->numColumns())) pTb->mergeCells(m_minRow, m_maxRow, m_minCol, m_maxCol); } }; typedef std::vector CellMerges; struct CellMargin { _DEFINE_(double, Left); _DEFINE_(double, Right); _DEFINE_(double, Top); _DEFINE_(double, Bottom); _DEFINE_(double, HorzSpacing); _DEFINE_(double, VertSpacing); CellMargin(): m_bUseLeft(false) , m_bUseRight(false) , m_bUseTop(false) , m_bUseBottom(false) , m_bUseHorzSpacing(false) , m_bUseVertSpacing(false) { } void apply2TableStyle(AcDbTableStyle *pTS, LPCTSTR pszCellStyle, const double &dPScale) { APPLY_MARGIN(Left); APPLY_MARGIN(Right); APPLY_MARGIN(Top); APPLY_MARGIN(Bottom); APPLY_MARGIN(HorzSpacing); APPLY_MARGIN(VertSpacing); } }; struct GridLineTypeProperty { int m_minRow, m_minCol; int m_maxRow, m_maxCol; double m_dPScale; AcDb::GridLineType m_type; _DEFINE_(AcDb::GridLineStyle, LineStyle); _DEFINE_(AcDb::LineWeight, LineWeight); _DEFINE_(CString, Linetype); _DEFINE_(int, Color); _DEFINE_(AcDb::Visibility, Visibility); _DEFINE_(double, DoubleLineSpacing); GridLineTypeProperty(AcDb::GridLineType type , const int &minRow , const int &maxRow , const int &minCol , const int &maxCol , const double &dps ) : m_type(type) , m_dPScale(dps) , m_minRow(minRow) , m_maxRow(maxRow) , m_minCol(minCol) , m_maxCol(maxCol) , m_bUseLinetype(false) , m_bUseColor(false) , m_bUseLineStyle(false) , m_bUseLineWeight(false) , m_bUseVisibility(false) , m_bUseDoubleLineSpacing(false) { } void apply2Table(AcDbTable *pTb) const { CellMergeRange tempRange(m_minRow, m_maxRow, m_minCol, m_maxCol); // 先调整范围合法性 if (!tempRange.vaild(pTb->numRows(), pTb->numColumns())) return; int minRow = tempRange.m_minRow; int maxRow = tempRange.m_maxRow; int minCol = tempRange.m_minCol; int maxCol = tempRange.m_maxCol; for (int nRow(minRow); nRow <= maxRow; ++nRow) { for (int nCol(minCol); nCol <= maxCol; ++nCol) { APPLY_GRIDLINE_PROPERTY(LineStyle); APPLY_GRIDLINE_PROPERTY(LineWeight); APPLY_GRIDLINE_PROPERTY(Visibility); if (m_bUseDoubleLineSpacing) { pTb->setGridDoubleLineSpacing(nRow , nCol , m_type , m_DoubleLineSpacing * m_dPScale); } if (m_bUseColor) { AcCmColor clr; clr.setColorIndex(m_Color); pTb->setGridColor(m_type, nRow, nCol, clr); } if (m_bUseLinetype) { AcDbObjectId id(MKTABLE::getTextStyle(m_Linetype)); if (id.isValid()) pTb->setGridLinetype(nRow, nCol, m_type, id); } } } } }; typedef std::vector GridLineTypePropertys; struct GridLineType { _DEFINE_(GridLineTypePropertys, HorzTop); _DEFINE_(GridLineTypePropertys, HorzInside); _DEFINE_(GridLineTypePropertys, HorzBottom); _DEFINE_(GridLineTypePropertys, VertLeft); _DEFINE_(GridLineTypePropertys, VertInside); _DEFINE_(GridLineTypePropertys, VertRight); _DEFINE_(GridLineTypePropertys, HorzGridLineTypes); _DEFINE_(GridLineTypePropertys, VertGridLineTypes); _DEFINE_(GridLineTypePropertys, OuterGridLineTypes); _DEFINE_(GridLineTypePropertys, InnerGridLineTypes); _DEFINE_(GridLineTypePropertys, AllGridLineTypes); GridLineType(){ } void apply2Table(AcDbTable *pTb) const { APPLY_GRIDLINE_TYPE(HorzTop); APPLY_GRIDLINE_TYPE(HorzInside); APPLY_GRIDLINE_TYPE(HorzBottom); APPLY_GRIDLINE_TYPE(VertLeft); APPLY_GRIDLINE_TYPE(VertInside); APPLY_GRIDLINE_TYPE(VertRight); APPLY_GRIDLINE_TYPE(HorzGridLineTypes); APPLY_GRIDLINE_TYPE(VertGridLineTypes); APPLY_GRIDLINE_TYPE(OuterGridLineTypes); APPLY_GRIDLINE_TYPE(InnerGridLineTypes); APPLY_GRIDLINE_TYPE(AllGridLineTypes); } }; struct CellStyle { CString m_sName; _DEFINE_(CString, TextStyle); _DEFINE_(double, TextHeight); _DEFINE_(double, Rotation); _DEFINE_(int, Color); _DEFINE_(int, BackgroundColor); _DEFINE_(AcDb::CellAlignment, Alignment); _DEFINE_(CellMargin, Margin); _DEFINE_(bool, enableMergeAll); CellStyle(): m_sName(_T("")) , m_bUseColor(false) , m_bUseBackgroundColor(false) , m_bUseTextStyle(false) , m_bUseTextHeight(false) , m_bUseRotation(false) , m_bUseMargin(false) , m_bUseenableMergeAll(false) , m_bUseAlignment(false) { } void apply2CellStyle(AcDbTableStyle *pTS, const double &dPScale) { AcStringArray cellnames; pTS->getCellStyles(cellnames); if (cellnames.find((LPCTSTR)m_sName) == -1) { if (pTS->createCellStyle(m_sName) != Acad::eOk) return; } APPLY_CELL_STYLE(Alignment); APPLY_CELL_STYLE(Rotation); if (m_bUseTextHeight) { pTS->setTextHeight(m_TextHeight * dPScale, m_sName); } if (m_bUseColor) { AcCmColor clr; clr.setColorIndex(m_Color); pTS->setColor(clr, m_sName); } if (m_bUseBackgroundColor) { AcCmColor clr; clr.setColorIndex(m_BackgroundColor); pTS->setBackgroundColor(clr, m_sName); } if (m_bUseTextStyle) { AcDbObjectId tsId = MKTABLE::getTextStyle(m_TextStyle); if (tsId.isValid()) pTS->setTextStyle(tsId, m_sName); } if (m_bUseenableMergeAll) pTS->enableMergeAll(m_enableMergeAll, m_sName); if (m_bUseMargin) { m_Margin.apply2TableStyle(pTS, m_sName, dPScale); } } }; typedef std::map CellStyles; struct Cell { int row; int col; CString text; CString style; void apply2Table(AcDbTable *pTb) const { if (!pTb) return; pTb->setTextString(row, col, text); if (!style.IsEmpty()) pTb->setCellStyle(row, col, style); } }; typedef std::vector Cells, CellRowData; typedef std::vector CellTableData; struct TableStyle { CString m_sName; std::map m_cellStyles; }; typedef std::map TableStyles; struct DataContent { // 默认单元格样式,一定要设置,只能是_TITLE,_DATA,_HEADER // 因为这三种样式是 AcDbTableStyle 自带并且无法删除的 CString m_defCellStyle; CellTableData m_tableData; DataContent(LPCTSTR def): m_defCellStyle(def) {} }; typedef std::map DataContents; }