-
2021-08-03 11:17:05
目录
1.合并后文本显示的位置不变
1.1界面展示
下图中第2行是合并后的效果
1.2 AutoScanTable.h
#pragma once class AutoScanTable : public CListCtrl { public: enum ROWTYPE { AUTOSCAN_ROW_NORMAL = 0, AUTOSCAN_ROW_DTC = 1 }; private: unsigned int m_uRowHeight; CRect m_listRect; public: AutoScanTable(); virtual ~AutoScanTable(); protected: virtual void DoDataExchange(CDataExchange* pDX); DECLARE_MESSAGE_MAP() public: void SetRowHeigt(int nHeight); virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); afx_msg void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct); afx_msg void OnSize(UINT nType, int cx, int cy); };
1.3 AutoScanTable.cpp
#include "stdafx.h" #include "MainDisplay.h" #include "AutoScanTable.h" AutoScanTable::AutoScanTable() { m_uRowHeight = 60; } AutoScanTable::~AutoScanTable() { } void AutoScanTable::DoDataExchange(CDataExchange* pDX) { CListCtrl::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(AutoScanTable, CListCtrl) ON_WM_MEASUREITEM_REFLECT() ON_WM_MEASUREITEM() ON_WM_DRAWITEM() ON_WM_SIZE() END_MESSAGE_MAP() void AutoScanTable::SetRowHeigt(int nHeight) { m_uRowHeight = nHeight; CRect rcWin; GetWindowRect(&rcWin); WINDOWPOS wp; wp.hwnd = m_hWnd; wp.cx = rcWin.Width(); wp.cy = rcWin.Height(); wp.flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER; SendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp); } void AutoScanTable::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) { CListCtrl::OnMeasureItem(nIDCtl, lpMeasureItemStruct); } void AutoScanTable::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { lpMeasureItemStruct->itemHeight = m_uRowHeight; } void AutoScanTable::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); LVITEM lvi = { 0 }; lvi.mask = LVIF_STATE;//|LVIF_IMAGE; lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED; lvi.iItem = lpDrawItemStruct->itemID; BOOL bGet = GetItem(&lvi); BOOL bSelect = ((lvi.state & LVIS_DROPHILITED) || ((lvi.state & LVIS_SELECTED) && ((GetFocus() == this) || (GetStyle() & LVS_SHOWSELALWAYS)))); //画文本背景 CRect bgRect = lpDrawItemStruct->rcItem; if (bSelect)//设置选中颜色 { pDC->SetTextColor(RGB(255, 255, 255));//白色文本 pDC->FillRect(bgRect, &CBrush(RGB(88, 88, 88)));//深灰色背景 } else { int iRow = lvi.iItem; if (iRow % 2 == 0)//设置偶数行文字颜色和背景颜色 { pDC->SetTextColor(RGB(0, 0, 0));//黑色文本 pDC->FillRect(bgRect, &CBrush(RGB(128, 128, 128))); //灰色背景 } else//设置奇数行文字颜色和背景颜色 { pDC->SetTextColor(RGB(0, 0, 0));//黑色文本 pDC->FillRect(bgRect, &CBrush(RGB(227, 227, 227))); //白色背景 } } LVITEM itemParam; itemParam.iItem = lpDrawItemStruct->itemID; itemParam.iSubItem = 0; GetItem(&itemParam); //绘制文本 if (lpDrawItemStruct->itemAction & ODA_DRAWENTIRE) { //得到列数 //int nCollumn = GetHeaderCtrl()->GetItemCount(); //循环处理 CString szText; for (int i = 0; i < GetHeaderCtrl()->GetItemCount(); i++) { CRect rcItem; if (!GetSubItemRect(lpDrawItemStruct->itemID, i, LVIR_LABEL, rcItem)) { continue; } if ((0 != i) && (AUTOSCAN_ROW_NORMAL == itemParam.lParam)) { CPen pen(PS_SOLID, 1, RGB(255, 255, 255)); pDC->SelectObject(&pen); CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); pDC->SelectObject(pBrush); pDC->Rectangle(rcItem); } szText = GetItemText(lpDrawItemStruct->itemID, i); rcItem.left += 5; rcItem.right -= 1; pDC->DrawText(szText, lstrlen(szText), &rcItem, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE); } } } void AutoScanTable::OnSize(UINT nType, int cx, int cy) { CListCtrl::OnSize(nType, cx, cy); ShowScrollBar(SB_HORZ, FALSE);//隐藏水平滚动条 }
1.4 创建表格并添加内容
m_listCtrl.Create(WS_BORDER | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_OWNERDRAWFIXED, rect, this, IDC_LISTCTRL); //m_listCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | WS_VSCROLL); m_listCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | WS_VSCROLL); m_listCtrl.SetBkColor(RGB(227, 227, 227)); m_listCtrl.MoveWindow(GetClientRectEx()); m_listCtrl.InsertColumn(0, _T(""), LVCFMT_LEFT, 0);//第0列无法居中显示,一般将其隐藏 m_listCtrl.InsertColumn(1, _T("No"), LVCFMT_LEFT, 30); // 插入第2列的列名 m_listCtrl.InsertColumn(2, _T("Name"), LVCFMT_LEFT, 450); // 插入第3列的列名 m_listCtrl.InsertColumn(3, _T("State"), LVCFMT_LEFT, 70); // 插入第4列的列名 m_listCtrl.InsertColumn(4, _T("Operation"), LVCFMT_LEFT, 90); // 插入第4列的列名 m_listCtrl.SetColumnWidth(4, LVSCW_AUTOSIZE_USEHEADER); CString strNo; CString strName; CString strState; CString strOpt; for (int i = 0; i <= 2; i++) { strNo.Format(_T("%d"), i); strName.Format(_T("Ecu%d"), i); strState.Format(_T("未扫描"), 20 + i); strOpt = _T("进入系统"); LVITEM *item = new LVITEM; if (1 == i) { item->lParam = AutoScanTable::AUTOSCAN_ROW_DTC; } else { item->lParam = AutoScanTable::AUTOSCAN_ROW_NORMAL; } item->iItem = i; item->iSubItem = 0; item->mask = LVIF_PARAM; m_listCtrl.InsertItem(item); //m_listCtrl.InsertItem(i, _T("")); // 插入行 m_listCtrl.SetItemText(i, 1, strNo); m_listCtrl.SetItemText(i, 2, strName); m_listCtrl.SetItemText(i, 3, strState); m_listCtrl.SetItemText(i, 4, strOpt); }
1.5 核心代码说明
创建表格时:
m_scanList.Create(WS_BORDER | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER | LVS_OWNERDRAWFIXED, rect, this, IDC_LISTCTRL); //m_scanList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | WS_VSCROLL); //设置表格扩展样式时,千万不要加LVS_EX_GRIDLINES,此参数会给表格自动加上白色的网格线,不容易去掉 m_scanList.SetExtendedStyle(LVS_EX_FULLROWSELECT | WS_VSCROLL);
往表格中插入行时:
LVITEM *item = new LVITEM; if (1 == i) { //因为只会合并部分单元格,所以哪些单元格是需要合并的,我们可以在这里指定一个标识来区分 item->lParam = AutoScanTable::AUTOSCAN_ROW_DTC; } else { item->lParam = AutoScanTable::AUTOSCAN_ROW_NORMAL; } item->iItem = i;//行号 item->iSubItem = 0;//列号 item->mask = LVIF_PARAM;//这里必须用LVIF_PARAM,以使得能传递item->lParam的值 m_listCtrl.InsertItem(item);//插入一行
绘制单元格时:
//获取单元格信息,以读取itemParam.lParam LVITEM itemParam; itemParam.iItem = lpDrawItemStruct->itemID; itemParam.iSubItem = 0; GetItem(&itemParam); ... //在插入表格的行时,设置了itemParam.lParam,这里通过此值来判断是否为待合并的单元格 //不需要合并的单元格不会执行下面的代码 if ((0 != i) && (AUTOSCAN_ROW_NORMAL == itemParam.lParam)) { CPen pen(PS_SOLID, 1, RGB(255, 255, 255)); pDC->SelectObject(&pen); CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); pDC->SelectObject(pBrush); pDC->Rectangle(rcItem);//绘制一个白色边框的矩形 }
2.合并后文本居中显示
2.1 界面展示
下图中第2行是合并后的效果
2.2 AutoScanTable.cpp
要实现上面的效果,只需要拷贝本文“1.3章节”的代码,然后修改一下下面这个函数:
void AutoScanTable::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
void AutoScanTable::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); LVITEM lvi = { 0 }; lvi.mask = LVIF_STATE;//|LVIF_IMAGE; lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED; lvi.iItem = lpDrawItemStruct->itemID; BOOL bGet = GetItem(&lvi); BOOL bSelect = ((lvi.state & LVIS_DROPHILITED) || ((lvi.state & LVIS_SELECTED) && ((GetFocus() == this) || (GetStyle() & LVS_SHOWSELALWAYS)))); //画文本背景 CRect bgRect = lpDrawItemStruct->rcItem; if (bSelect)//设置选中颜色 { pDC->SetTextColor(RGB(255, 255, 255));//白色文本 pDC->FillRect(bgRect, &CBrush(RGB(88, 88, 88)));//深灰色背景 } else { int iRow = lvi.iItem; if (iRow % 2 == 0)//设置偶数行文字颜色和背景颜色 { pDC->SetTextColor(RGB(0, 0, 0));//黑色文本 pDC->FillRect(bgRect, &CBrush(RGB(128, 128, 128))); //灰色背景 } else//设置奇数行文字颜色和背景颜色 { pDC->SetTextColor(RGB(0, 0, 0));//黑色文本 pDC->FillRect(bgRect, &CBrush(RGB(227, 227, 227))); //白色背景 } } LVITEM itemParam; itemParam.iItem = lpDrawItemStruct->itemID; itemParam.iSubItem = 0; GetItem(&itemParam); //绘制文本 if (lpDrawItemStruct->itemAction & ODA_DRAWENTIRE) { //得到列数 //int nCollumn = GetHeaderCtrl()->GetItemCount(); //循环处理 CString szText; CRect totalRect; for (int i = 0; i < GetHeaderCtrl()->GetItemCount(); i++) { CRect rcItem; if (!GetSubItemRect(lpDrawItemStruct->itemID, i, LVIR_LABEL, rcItem)) { continue; } //记录单元格位置 if (0 == i) { totalRect = rcItem; } else { totalRect.right = rcItem.right; totalRect.bottom = rcItem.bottom; } if ((0 != i) && (AUTOSCAN_ROW_NORMAL == itemParam.lParam)) { CPen pen(PS_SOLID, 1, RGB(255, 255, 255)); pDC->SelectObject(&pen); CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); pDC->SelectObject(pBrush); pDC->Rectangle(rcItem); szText = GetItemText(lpDrawItemStruct->itemID, i); rcItem.left += 5; rcItem.right -= 1; pDC->DrawText(szText, lstrlen(szText), &rcItem, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE); } //记录每个单元格的文本 szText += GetItemText(lpDrawItemStruct->itemID, i); szText += "--"; } //将合并后的文本一次性显示出来 totalRect.left += 230; totalRect.right -= 230; pDC->DrawText(szText, lstrlen(szText), &totalRect, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE); } }
更多相关内容 -
【知识兔】Excel教程:批量合并相同内容单元格神技
2021-11-18 02:16:52大家好,今天知识兔跟大家分享一下关于批量合并相同内容单元格的方法有哪些,这是一位同学在群里求助的案例,当时群内针对这个问题各位小伙伴们抛出了多种解决方法,索性知识兔小编就整理成专题文章来跟大家分享一下...大家好,今天知识兔跟大家分享一下关于批量合并相同内容单元格的方法有哪些,这是一位同学在群里求助的案例,当时群内针对这个问题各位小伙伴们抛出了多种解决方法,索性知识兔小编就整理成专题文章来跟大家分享一下,需求的效果图如下:
因为部门有很多相同的,所以现在需要将相同的部门合并成一个。
方法1:分类汇总后合并单元格再格式刷
这个方法是小编知道最早流传的经典操作技巧之一,我们先选中需要合并单元格字段列的单元格区域,在数据选项卡中的分级显示找到分类汇总,选择后会弹出一个提示,我们确定后会按照部门列字段进行分类汇总,接着对左边多出来的汇总列区域选中,按快捷键Ctrl+G或者F5定位空值,然后在开始选项卡中将定位的空单元格合并。详解:Excel 2019零基础小白逆袭Excel大神全套视频教程 | 知识兔
继续选中D列部门字段单元格区域,再次打开分类汇总对话框,然后点击全部删除,把多余的C列删除。这样操作下来,部门字段中相同内容的单元格就全部被合并了。
方法2:WPS表格一键合并相同内容单元格
近两年来,国产办公软件WPS发展迅速,结合国人办公需求,WPS软件会动态更新,里面增加了许多微软Office没有的功能,比如今天聊到的合并相同内容单元格,WPS软件相对前面的操作更加简单,一键搞定,操作图示如下:Excel 2019零基础小白逆袭Excel大神全套视频教程 | 知识兔
方法3:第三方插件合并相同内容单元格
小伙伴们看到了WPS都有内置合并功能,不由自主的就说如果Office有的话那就完美了,其实这个通过第三方的插件也是可以实现的,因为现在会编写VBA代码进行封装的大牛很多,比如下面的方方格子插件就内嵌了一键合并的功能,今天只做效果展示,不提供软件下载哈,感兴趣的小伙伴可以去度娘找软件官网下载体验。
方法4:编写宏代码合并相同单元格
上面的第三方插件其实就是VBA编写好的代码通过封装后加载到了我们软件功能区中,如果您的电脑没有安装WPS,也无法安装插件,又不想用文章开头第一种方法,那么小编最后的建议您可以编写一段VBA代码来完成。
-
datatables 合并单元格(rowspan)
2019-12-12 14:53:52并没有具体的说怎么去动态的合并tbody下的单元格 查阅资料有一下几种,统计几篇可行的文章先做记录,再行研究 防止原博主博文删除: 第一种: DataTables实现rowspan思路: <table id="example" class=...目前在项目中我们用到的是datatable插件。在官网中有一定的例子介绍的是复杂的合并表头。并没有具体的说怎么去动态的合并tbody下的单元格
查阅资料有一下几种,统计几篇可行的文章先做记录,再行研究 防止原博主博文删除:
第一种:
<table id="example" class="display table table-bordered" cellspacing="0" width="600" style="margin-top: 50px"> <thead> <tr> <th>Name</th> <th>Position</th> <th>Age</th> </tr> </thead> </table>
var dataSet = [ [ "Tiger Nixon", "Edinburgh",20,1 ], [ "Garrett Winters", "Tokyo",22,2], [ "Ashton Cox", "Tokyo",21,0 ] ]; $('#example').DataTable({ data: dataSet, paging: true, searching:false, //搜索栏 lengthChange : false, //是否允许改变每页显示的数据条数 ordering:false, columnDefs: [{ targets: 1, createdCell: function (td, cellData, rowData, row, col) { var rowspan = rowData[3]; if (rowspan > 1) { $(td).attr('rowspan', rowspan) } if (rowspan == 0) { $(td).remove(); } } }] });
说明一下:要实现rowspan/colspan这样的特殊效果需要用到createdCell回调函数,此函数可配置在columns配置中,亦可配置在columnDefs中,此例采用columnDefs配置实现。具体原理是,在创建单元格cell的是否控制怎样渲染,后台需要定义好rowspan的值,这个需要后台想办法给出这个值。
后台给出rowspan的思路:
将需要分组的属性构造Map<key,count> map,遍历list得到map,再遍历list设置rowspan=map.get(key),get过的key设置0再get, OK, 搞定
具体实现:
http://www.cnblogs.com/hdwang/p/7169255.html
效果图如上。
2.html代码,含js代码
2.1 common.js
/** * Created by hdwang on 2017/6/23. */ var language = { "search": "", "sSearch" : "搜索", "sUrl" : "", "sProcessing" : "正在加载数据...", "sLengthMenu" : "显示_MENU_条 ", "sZeroRecords" : "没有您要搜索的内容", "sInfo" : "从_START_ 到 _END_ 条记录——总记录数为 _TOTAL_ 条", "sInfoEmpty" : "记录数为0", "sInfoFiltered" : "(全部记录数 _MAX_ 条)", "sInfoPostFix" : "", "oPaginate": { "sFirst" : "第一页", "sPrevious" : " 上一页 ", "sNext" : " 下一页 ", "sLast" : " 最后一页 " } }; /** * 将参数对象转换成url查询参数 * @param params 参数对象 * @returns {string} url查询参数 */ function getUrlParams(params) { var queryStr = ''; var isFirstParam = true; for(var key in params){ if(isFirstParam){ queryStr += key + '=' + params[key]; isFirstParam = false; }else{ queryStr += '&' + key + '=' + params[key]; } } return queryStr; }
2.2 home.ftl
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <title>cpm system</title> <!-- Bootstrap --> <link href="/thirdlib/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <!-- datatables --> <link href="/thirdlib/datatables/css/jquery.dataTables.min.css" rel="stylesheet"/> <link href="/css/common.css" rel="stylesheet" /> </head> <body> <div id="tableArea" style="padding: 100px;"> <div> <a href="/home/export">导出</a> </div> <table id="rowspanTable" class="table table-bordered"> <thead> <th>地区</th> <th>公司</th> <th>部门</th> <th>员工姓名</th> </thead> </table> </div> </body> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="/thirdlib/jquery/jquery-2.0.3.min.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="/thirdlib/bootstrap/js/bootstrap.min.js"></script> <!-- datatables --> <script src="/thirdlib/datatables/js/jquery.dataTables.min.js"></script> <script src="/js/common.js"></script> <script type="text/javascript"> $(function(){ $('#rowspanTable').dataTable( { "paging": true, "processing": true, "serverSide": true, "searching":false, //搜索栏 "lengthChange" : false, //是否允许改变每页显示的数据条数 "pageLength": 10, //每行显示记录数 "info":true, //开启Datatables信息显示(记录数等) "ordering":false, //全局定义是否启用排序,优先级比columns.orderable高 "language": language, "ajax": { "url": "/home/query", "type": "POST" }, "columns": [ {"data":"area", "orderable": false,"searchable": false}, { "data": "company", "orderable": false ,"searchable": false}, { "data": "department", "orderable": false,"searchable": false }, { "data": "userName", "orderable": false ,"searchable": false} ], "columnDefs": [{ targets: [0,1,2], //第1,2,3列 createdCell: function (td, cellData, rowData, row, col) { var rowspan = 1; if(col == 0){ rowspan = rowData.areaRowSpan; } if(col ==1){ rowspan = rowData.companyRowSpan; } if(col ==2){ rowspan = rowData.departmentRowSpan; } if (rowspan > 1) { $(td).attr('rowspan', rowspan) } if (rowspan == 0) { $(td).remove(); } } }] } ); }); </script> </html>
3.后台代码
3.1 分页参数对象
/** * Created by hdwang on 2017/6/22. * 分页参数 */ public class PageParam { /** * 第几次绘画(前端标识) */ private int draw; /** * 起始记录(从0开始),mysql也是从0开始,吻合,good! */ private int start; /** * 页大小 */ private int length; public int getDraw() { return draw; } public void setDraw(int draw) { this.draw = draw; } public int getStart() { return start; } public void setStart(int start) { this.start = start; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } /** * 第几页(0-n) */ public int getPage(){ return this.start/this.length; } }
3.2 数据返回对象
import java.util.List; /** * Created by hdwang on 2017/6/22. * 表格数据(datatables) */ public class TableData<T> { /** * 第几次绘画(前端标识) */ private int draw; /** * 行过滤(不知道干嘛的) */ private int recordsFiltered; /** * 总行数 */ private int recordsTotal; /** * 行数据 */ private List<T> data; /** * 起始记录(用于前端初始化序列号用的) */ private int start; /** * 错误信息 */ private String error; public int getDraw() { return draw; } public void setDraw(int draw) { this.draw = draw; } public int getRecordsFiltered() { return recordsFiltered; } public void setRecordsFiltered(int recordsFiltered) { this.recordsFiltered = recordsFiltered; } public int getRecordsTotal() { return recordsTotal; } public void setRecordsTotal(int recordsTotal) { this.recordsTotal = recordsTotal; } public List<T> getData() { return data; } public void setData(List<T> data) { this.data = data; } public int getStart() { return start; } public void setStart(int start) { this.start = start; } public String getError() { return error; } public void setError(String error) { this.error = error; } }
3.3 数据实体对象
import java.io.Serializable; /** * Created by hdwang on 2017/7/14. */ public class Member{ private String area; private String company; private String department; private String userName; private Integer areaRowSpan; private Integer companyRowSpan; private Integer departmentRowSpan; public Member(String area,String company,String department,String userName){ this.area = area; this.company = company; this.department = department; this.userName = userName; } public String getArea() { return area; } public void setArea(String area) { this.area = area; } public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Integer getAreaRowSpan() { return areaRowSpan; } public void setAreaRowSpan(Integer areaRowSpan) { this.areaRowSpan = areaRowSpan; } public Integer getCompanyRowSpan() { return companyRowSpan; } public void setCompanyRowSpan(Integer companyRowSpan) { this.companyRowSpan = companyRowSpan; } public Integer getDepartmentRowSpan() { return departmentRowSpan; } public void setDepartmentRowSpan(Integer departmentRowSpan) { this.departmentRowSpan = departmentRowSpan; } }
3.4 导出相关类
/** * Created by hdwang on 2017/7/14. */ public class ExcelData { private String value;//单元格的值 private int colSpan = 1;//单元格跨几列 private int rowSpan = 1;//单元格跨几行 private boolean alignCenter;//单元格是否居中,默认不居中,如果选择是,则水平和上下都居中 public boolean isAlignCenter() { return alignCenter; } public void setAlignCenter(boolean alignCenter) { this.alignCenter = alignCenter; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public int getColSpan() { return colSpan; } public void setColSpan(int colSpan) { this.colSpan = colSpan; } public int getRowSpan() { return rowSpan; } public void setRowSpan(int rowSpan) { this.rowSpan = rowSpan; } }
package com.xincheng.cpm.common; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.util.List; /** * Created by hdwang on 2017/7/14. */ public class ExcelUtil { /** * 生成excel工作簿 * @param sheetTitle sheet名称 * @param titles 标题 * @param rows 行数据 * @return 工作簿 */ public XSSFWorkbook execute(String sheetTitle,String[] titles,List<List<ExcelData>> rows) { //定义工作簿 XSSFWorkbook workbook = new XSSFWorkbook(); //th样式 CellStyle titleStyle = workbook.createCellStyle(); titleStyle.setBorderBottom((short) 1); titleStyle.setBorderRight((short)1); titleStyle.setBorderLeft((short)1); titleStyle.setBorderTop((short)1); titleStyle.setVerticalAlignment((short)1); titleStyle.setAlignment((short)2); XSSFFont font = workbook.createFont(); font.setBold(true); titleStyle.setFont(font); //td样式 CellStyle style = workbook.createCellStyle(); style.setBorderBottom((short)1); style.setBorderRight((short)1); style.setBorderLeft((short)1); style.setBorderTop((short)1); style.setVerticalAlignment((short)1); //创建工作表 XSSFSheet sheet = workbook.createSheet(sheetTitle); sheet.setDefaultRowHeightInPoints(20.0F); //创建标题行 XSSFRow titleRow = sheet.createRow(0); for(int col=0;col<titles.length;col++) { //遍历列 Cell cell = titleRow.createCell(col); cell.setCellStyle(titleStyle); cell.setCellValue(titles[col]); for(int row=0;row<rows.size();row++){ //遍历行 int rowIndex = row+1; XSSFRow contentRow = sheet.getRow(rowIndex); if(contentRow == null){ contentRow = sheet.createRow(rowIndex); } ExcelData data = rows.get(row).get(col); Cell contentRowCell = contentRow.createCell(col); contentRowCell.setCellStyle(style); contentRowCell.setCellValue(data.getValue()); //合并单元格 if (data.getColSpan() > 1 || data.getRowSpan() > 1) { CellRangeAddress cra = new CellRangeAddress(rowIndex, rowIndex + data.getRowSpan() - 1, col, col + data.getColSpan() - 1); sheet.addMergedRegion(cra); } } } return workbook; } }
3.5 controller层
package com.xincheng.cpm.controller; import com.chenrd.common.excel.ExportExcel; import com.xincheng.cpm.common.*; import com.xincheng.cpm.entity.cpm.User; import com.xincheng.cpm.service.UserService; import com.xincheng.cpm.vo.IncomeDailyVO; import org.apache.commons.lang3.StringUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.util.*; /** * Created by hdwang on 2017/6/19. */ @Controller @RequestMapping("/home") public class HomeController { @Autowired UserService userService; @RequestMapping("") public String index(HttpSession session, ModelMap map, HttpServletRequest request){ User user = (User) session.getAttribute("user"); map.put("user",user); return "home"; } @RequestMapping(value="/query",method= RequestMethod.POST) @ResponseBody public TableData<Member> getUserByPage(PageParam pageParam, User user){ Page<Member> userPage = this.getMembers(pageParam); TableData<Member> datas = new TableData<>(); datas.setDraw(pageParam.getDraw()); datas.setStart(pageParam.getStart()); datas.setData(userPage.getContent()); datas.setRecordsFiltered((int)userPage.getTotalElements()); datas.setRecordsTotal((int)userPage.getTotalElements()); return datas; } private Page<Member> getMembers(PageParam pageParam) { //1.模拟数据库查询 Pageable pageable = new PageRequest(pageParam.getPage(), pageParam.getLength()); long count = 6; List<Member> members = getMembersFromDb(); //2.计算rowspan this.countRowspan(members); Page<Member> memberPage = new PageImpl<Member>(members,pageable,count); return memberPage; } private void countRowspan(List<Member> members) { Map<String,Integer> propertyCountMap = this.countPropertyCount(members); List<String> hadGetKeys = new ArrayList<>(); //曾经取过的key for(Member member:members){ String areaKey = member.getArea(); String companyKey = areaKey+member.getCompany(); String departmentKey = companyKey+ member.getDepartment(); Integer areaCount = propertyCountMap.get(areaKey); if(areaCount == null){ member.setAreaRowSpan(1); }else{ if(hadGetKeys.contains(areaKey)){ member.setAreaRowSpan(0); //曾经取过 }else{ member.setAreaRowSpan(areaCount); //第一次取 hadGetKeys.add(areaKey); } } Integer companyCount = propertyCountMap.get(companyKey); if(companyCount == null){ member.setCompanyRowSpan(1); }else { if(hadGetKeys.contains(companyKey)){ member.setCompanyRowSpan(0); }else{ member.setCompanyRowSpan(companyCount); hadGetKeys.add(companyKey); } } Integer departmentCount = propertyCountMap.get(departmentKey); if(companyCount == null){ member.setDepartmentRowSpan(1); }else { if(hadGetKeys.contains(departmentKey)){ member.setDepartmentRowSpan(0); }else{ member.setDepartmentRowSpan(departmentCount); hadGetKeys.add(departmentKey); } } } } private List<Member> getMembersFromDb() { Member member1 = new Member("安徽","A","人力资源部"," 小红"); Member member2 = new Member("安徽","B","人力资源部"," 小明"); Member member3 = new Member("浙江","C","人力资源部"," 小君"); Member member4 = new Member("浙江","C","技术部"," 小王"); Member member5 = new Member("浙江","D","技术部"," 小李"); Member member6 = new Member("浙江","D","人力资源部"," 小刚"); List<Member> members = new ArrayList<>(); members.add(member1); members.add(member2); members.add(member3); members.add(member4); members.add(member5); members.add(member6); return members; } /** * 统计每个字段的每组成员个数 * @param rows 记录 * @return 每个字段的每组成员个数 */ private Map<String,Integer> countPropertyCount(List<Member> rows){ Map<String,Integer> propertyCountMap = new HashMap<>(); for(Member member:rows){ // "area": 无父级分组 String area = member.getArea(); if(propertyCountMap.get(area) == null){ propertyCountMap.put(area,1); }else{ int count = propertyCountMap.get(area); propertyCountMap.put(area,count+1); } // "company":有area父组 String company = member.getCompany(); String uniqueParent = member.getArea(); String key = uniqueParent + company; if(propertyCountMap.get(key) == null){ propertyCountMap.put(key,1); }else{ int count = propertyCountMap.get(key); propertyCountMap.put(key,count+1); } // "department": 有area,company这两个父组 String department = member.getDepartment(); uniqueParent = member.getArea()+member.getCompany(); key = uniqueParent + department; if(propertyCountMap.get(key) == null){ propertyCountMap.put(key,1); }else{ int count = propertyCountMap.get(key); propertyCountMap.put(key,count+1); } } return propertyCountMap; } @RequestMapping("/export") public void export(HttpServletResponse response) throws IOException { List<Member> members = this.getMembersFromDb(); this.countRowspan(members); List<List<ExcelData>> rows = new ArrayList<>(); for(Member member:members){ List<ExcelData> row = new ArrayList<>(); ExcelData col1 = new ExcelData(); col1.setValue(member.getArea()); col1.setRowSpan(member.getAreaRowSpan()); row.add(col1); ExcelData col2 = new ExcelData(); col2.setValue(member.getCompany()); col2.setRowSpan(member.getCompanyRowSpan()); row.add(col2); ExcelData col3 = new ExcelData(); col3.setValue(member.getDepartment()); col3.setRowSpan(member.getDepartmentRowSpan()); row.add(col3); ExcelData col4 = new ExcelData(); col4.setValue(member.getUserName()); row.add(col4); rows.add(row); } OutputStream outputStream = response.getOutputStream(); try { String filename = URLEncoder.encode("员工" + ".xlsx", "UTF-8"); response.setContentType("application/vnd.ms-excel"); response.addHeader("Content-Disposition", "octet-stream;filename=" + filename); ExcelUtil excelUtil = new ExcelUtil(); XSSFWorkbook workbook = excelUtil.execute("sheet1",new String[]{"地区","公司","部门","员工姓名"},rows); workbook.write(outputStream); } finally { if (outputStream != null) outputStream.close(); } } }
导出excel功能使用poi类库实现。至此,页面展示和导出均OK!
以上参考链接:https://www.cnblogs.com/hdwang/p/7115835.html
https://www.cnblogs.com/hdwang/p/7169255.html?utm_source=itdadao&utm_medium=referral
https://blog.csdn.net/u011974797/article/details/77983645
第二种:(第二篇文章)
原文地址:https://github.com/ssy341/datatables-cn/issues/211#issuecomment-372928301
"drawCallback": function (settings) {// var api = this.api(); var rows = api.rows({ page: 'current' }).nodes(); // console.log('idx = ' + rows[0].cells.length); var idx = 0; // 第一列进行合并 var last = null; var tr = null; var ltd = null; api.column(idx, { page: 'current' }).data().each(function (group, i) { tr = $(rows[i]); var td = $("td:eq(" + idx + ")", tr); if (last !== group) { td.attr("rowspan", 1); td.text(group); ltd = td; last = group; td.css("vertical-align", "middle"); } else { ltd.attr("rowspan", parseInt(ltd.attr("rowspan")) + 1); td.remove(); } }); idx = 1//稍微修改了一下。根据项目需要完成第一列和第二列前五行的单元格合并 last = null; tr = null; ltd = null; api.column(idx, { page: 'current' }).data().each(function (group, i) { tr = $(rows[i]); var td = $("td:eq(" + idx + ")", tr); if (last !== group) { td.attr("rowspan", 1); td.text(group); ltd = td; last = group; td.css("vertical-align", "middle"); idx = 0; } else { ltd.attr("rowspan", parseInt(ltd.attr("rowspan")) + 1); td.remove(); if (parseInt(ltd.attr("rowspan")) === 5) { idx = 1;//第二个五行 } } }); },
第三种(篇):datatables 多列 行合并
原文地址:https://www.jianshu.com/p/ff094dc360f4
1、行合并想要的样式如下,需要合并4列的行,如下图(数据为模拟数据,如有雷同,纯属人品爆发)
##controller代码: // 计算计划类型的合并的planRowSpan int tiefaRowSpan = Integer.parseInt(String.valueOf(statisticsTieFaConList.size())); int tiedaoRowSpan = Integer.parseInt(String.valueOf(statisticsTieDaoConList.size())); // 客户所在位置下标 int logFlag = 0; // 客户名称1,是判断标准 String logName1 = ""; // 客户名称2,随着循环变化 String logName2 = ""; // 客户的合并的行数 int logRowSpan = 1; // 供应商所在位置下标 int supFlag = 0; // 供应商名称1,是判断标准 String supName1 = ""; // 供应商名称2,随着循环变化 String supName2 = ""; // 供应商的合并的行数 int supRowSpan = 1; // 货票号所在位置下标 int cargoFlag = 0; // 货票号1,是判断标准 String cargoName1 = ""; // 货票号2,随着循环变化 String cargoName2 = ""; // 货票号的合并的行数 int cargoRowSpan = 1; // 计算行的合并的rowspan的值 1、planRowSpan:计划类型,2、logRowSpan:客户公司,3、supRowSpan:运输公司,4、cargoRowSpan:货票号 for (int i=0; i < resultList.size(); i++) { // 因为铁发和铁到是按照类别分开的,所以按照铁发的数量进行判断的分割 if (i == 0) { resultList.get(i).put("planRowSpan", tiefaRowSpan); logFlag = i; logName1 = String.valueOf(resultList.get(i).get("logCompany")); supFlag = i; supName1 = String.valueOf(resultList.get(i).get("supCompany")); cargoFlag = i; cargoName1 = String.valueOf(resultList.get(i).get("cargobillCode")); } else if (i < tiefaRowSpan){ resultList.get(i).put("planRowSpan", 0); } else if (i == tiefaRowSpan) { resultList.get(i).put("planRowSpan", tiedaoRowSpan); resultList.get(supFlag).put("supRowSpan", supRowSpan); resultList.get(cargoFlag).put("cargoRowSpan", cargoRowSpan); supFlag = i; supName1 = String.valueOf(resultList.get(i).get("supCompany")); cargoFlag = i; cargoName1 = String.valueOf(resultList.get(i).get("cargobillCode")); } else if (i > tiefaRowSpan) { resultList.get(i).put("planRowSpan", 0); } // 取物流商的名称进行对比 if (i != 0 && i != tiefaRowSpan) { logName2 = String.valueOf(resultList.get(i).get("logCompany")); supName2 = String.valueOf(resultList.get(i).get("supCompany")); cargoName2 = String.valueOf(resultList.get(i).get("cargobillCode")); if (logName1.equals(logName2)) { logRowSpan = logRowSpan + 1; resultList.get(i).put("logRowSpan", 0); if (supName1.equals(supName2)) { supRowSpan = supRowSpan + 1; resultList.get(i).put("supRowSpan", 0); if (cargoName1.equals(cargoName2)) { cargoRowSpan = cargoRowSpan + 1; resultList.get(i).put("cargoRowSpan", 0); } else { resultList.get(cargoFlag).put("cargoRowSpan", cargoRowSpan); cargoFlag = i; cargoRowSpan = 1; cargoName1 = String.valueOf(resultList.get(i).get("cargobillCode")); cargoName2 = ""; } } else { resultList.get(supFlag).put("supRowSpan", supRowSpan); supFlag = i; supRowSpan = 1; supName1 = String.valueOf(resultList.get(i).get("supCompany")); supName2 = ""; resultList.get(cargoFlag).put("cargoRowSpan", cargoRowSpan); cargoFlag = i; cargoRowSpan = 1; cargoName1 = String.valueOf(resultList.get(i).get("cargobillCode")); cargoName2 = ""; } } else { resultList.get(logFlag).put("logRowSpan", logRowSpan); logFlag = i; logRowSpan = 1; logName1 = String.valueOf(resultList.get(i).get("logCompany")); logName2 = ""; resultList.get(supFlag).put("supRowSpan", supRowSpan); supFlag = i; supRowSpan = 1; supName1 = String.valueOf(resultList.get(i).get("supCompany")); supName2 = ""; resultList.get(cargoFlag).put("cargoRowSpan", cargoRowSpan); cargoFlag = i; cargoRowSpan = 1; cargoName1 = String.valueOf(resultList.get(i).get("cargobillCode")); cargoName2 = ""; } } else if (i == tiefaRowSpan) { resultList.get(logFlag).put("logRowSpan", logRowSpan); logFlag = i; logRowSpan = 1; logName1 = String.valueOf(resultList.get(i).get("logCompany")); logName2 = ""; resultList.get(supFlag).put("supRowSpan", supRowSpan); supFlag = i; supRowSpan = 1; supName1 = String.valueOf(resultList.get(i).get("supCompany")); supName2 = ""; resultList.get(cargoFlag).put("cargoRowSpan", cargoRowSpan); cargoFlag = i; cargoRowSpan = 1; cargoName1 = String.valueOf(resultList.get(i).get("cargobillCode")); cargoName2 = ""; } } resultList.get(logFlag).put("logRowSpan", logRowSpan); resultList.get(supFlag).put("supRowSpan", supRowSpan); resultList.get(cargoFlag).put("cargoRowSpan", cargoRowSpan); ##js代码: "ordering" : false, // 按照最新下发的订单,订单编码是升序的排列顺序 // order: [[ 5, "desc" ]], columnDefs: [{ targets: [0,1,2,3], //第1,2,3列 createdCell: function (td, cellData, rowData, row, col) { var rowspan = 1; if(col == 0){ rowspan = rowData.planRowSpan; } if(col == 1){ rowspan = rowData.logRowSpan; } if(col == 2){ rowspan = rowData.supRowSpan; } if(col == 3){ rowspan = rowData.cargoRowSpan; } if (rowspan > 1) { $(td).attr('rowspan', rowspan) } if (rowspan == 0) { $(td).remove(); } } }],
第四篇文章 datatables 分多行 合并单元格:http://blog.sina.com.cn/s/blog_b92442710102wfhu.html
function Deployment_map_DataTable2() { //datatables的数据请求 //重绘 if ( $.fn.dataTable.isDataTable( '#Deployment_point_datatables1bottom' ) ) { var table1 = $('#Deployment_point_datatables1bottom').DataTable(); table1.destroy(); $('#Deployment_point_datatables1bottom').empty(); $('#Deployment_point_datatables1bottom').after(' '); console.log(3); } //重绘 if ( $.fn.dataTable.isDataTable( '#Deployment_point_datatables2bottom' ) ) { var table2 = $('#Deployment_point_datatables2bottom').DataTable(); table2.destroy(); $('#Deployment_point_datatables2bottom').empty(); console.log(4); } var dataSet=[ ['2','东小口镇','256','大望村','300'], ['2','东小口镇','256','大望村','300'], ['2','东小口镇','256','大望村','300'], ['3','东小口镇','256','大望村','300'], ['3','东小口镇','256','大望村','300'], ['3','东小口镇','256','大望村','300'], ] var t = $('#Deployment_point_datatables2bottom').DataTable( { "bAutoWidth":false, "processing": true, "bProcessing": true, "searching":false, "oLanguage" :{ "sLengthMenu": "每页显示 _MENU_ 条", "sZeroRecords": "抱歉, 没有找到", "sInfo": "从 _START_ 到 _END_ /共 _TOTAL_ 条数据", "sInfoEmpty": "没有数据", "sInfoFiltered": "(从 _MAX_ 条数据中检索)", "sZeroRecords": "没有检索到数据", "sSearch": "搜索", "oPaginate": { "sFirst": "首页", "sPrevious": "前一页", "sNext": "后一页", "sLast": "尾页" } }, "scrollY": "300px", "scrollCollapse": "true", "paging": "false", "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]], "data": dataSet, rowsGroup: [ 0, 1, 2 ], "columns": [ { "title": "排名" }, { "title": "名称" }, { "title": "PM2.5" }, { "title": "区域监点" }, { "title": "PM2.5" } ] } ); };
第五篇:
我的需求与这种相似 都需要多列的单元格合并 并且比这种稍微复杂 一列合并一个单元格后还得分两列
然后贴上代码吧。
首先是模拟的数据。
var returnData=[
{id:"item_1",name:"财务管理流程",comp:"支付管理",Pjtime:"2015年-2017年",Tjtime:"2017-10-15",main:"1.获取测试期间内付款申请样本、月度资金计划及合同等支持性文件;2.检查付款申请事项是否在月度资金计划内",mode:"控制测试",choose:"是",proof:"查看",details:"查看",merge:3,imerge:1},
{id:"item_2",name:"财务管理流程",comp:"支付管理",Pjtime:"2015年-2017年",Tjtime:"2017-10-15",main:"检查付款信息是否正确,主要包括:收款单位名称、申请支付金额和支付摘要等;",mode:"控制测试",choose:"否",proof:"查看",details:"查看",merge:0,imerge:2},
{id:"item_3",name:"财务管理流程",comp:"支付管理",Pjtime:"2015年-2017年",Tjtime:"2017-10-15",main:"1.获取测试期间内付款申请样本、月度资金计划及合同等支持性文件;2.检查付款申请事项是否在月度资金计划内",mode:"控制测试",choose:"是",proof:"查看",details:"查看",merge:0,imerge:0},
{id:"item_4",name:"财务管理流程",comp:"支付管理",Pjtime:"2015年-2017年",Tjtime:"2017-10-15",main:"检查付款信息是否正确,主要包括:收款单位名称、申请支付金额和支付摘要等;",mode:"控制测试",choose:"是",proof:"查看",details:"查看",merge:3,imerge:1},
{id:"item_5",name:"财务管理流程",comp:"支付管理",Pjtime:"2015年-2017年",Tjtime:"2017-10-15",main:"检查付款信息是否正确,主要包括:收款单位名称、申请支付金额和支付摘要等;",mode:"控制测试",choose:"是",proof:"查看",details:"查看",merge:0,imerge:2},
{id:"item_6",name:"财务管理流程",comp:"支付管理",Pjtime:"2015年-2017年",Tjtime:"2017-10-15",main:"检查付款信息是否正确,主要包括:收款单位名称、申请支付金额和支付摘要等;",mode:"控制测试",choose:"是",proof:"查看",details:"查看",merge:0,imerge:0}
];$('#lx_namePj_table').dataTable( data: returnData, //模拟的数据sDom: '"top"i',
pageLength: 6,//每页显示的条数
autoWidth: false,
destroy: true,
info: true,
scrollX:true, //横向滚动条
columns: [
{"data": null, title: "序号", "width": "8%"},
{"data": "id", visible:false},
{"data": "name", title: "一级流程", "width": "15%"},
{"data": "comp", title: "末级流程", "width": "15%"},
{"data": "Pjtime",title: "控制点编号", "width": "15%"},
{"data": "Tjtime",title: "控制点描述", "width": "15%"},
{"data": "main",title: "评价要点", "width": "40%"},
{"data": "mode",title: "测试方式", "width": "15%"},
{"data": "choose",title: "是否存在缺陷", "width": "15%"},
{"data": "proof",title: "佐证", "width": "15%"},
{"data": "details",title: "缺陷详情", "width": "15%"}
],"fnDrawCallback": function () {
this.api().column(0).nodes().each(function (cell, i) {
cell.innerHTML = i + 1;
});
},
"columnDefs": [{ //重要的部分
targets: [2,3], //要合并的列数(第1,2,3列)
createdCell: function (td, cellData, rowData, row, col) { //重要的操作可以合并列的代码
var rowspan = rowData.merge;//这里主要是利用了模拟数据中的merge来控制
if (rowspan > 1) { //这里做的判断。相信大家也能看懂的。
$(td).attr('rowspan', rowspan)
}
if (rowspan == 0) {
$(td).remove();
}
},
"data": "culture_title",
"render": function (data, type, full) {
return "<span title='" + data + "'>" + data + "</span>";
}
},{
targets: [7,8,9,10], //第1,2,3列 //这块是另外一模块的合并。所以是写成了对象的形式。
createdCell: function (td, cellData, rowData, row, col) { //和上面一样的思想
var rowspan = rowData.imerge;
if (rowspan > 1) {
$(td).attr('rowspan', rowspan)
}
if (rowspan == 0) {
$(td).remove();
}
}
}]});
最后来说下数据中的merge和imerge代表的意思
merge是第一次要合并的数据值 3.是代表的要合并的行数、如果要合并的话。就在具体的行数上写合并的行数。例如:3.不合并的写1.但在合并的行后边要写上0.也就是不合并的意思。
imerge也是这样的思想。
-
如何批量合并相同内容的单元格
2014-01-14 14:20:16大千世界,无奇不有,我们一方面苦口婆心让人别用合并,取消合并,但还有很多人是需要把数据合并的,这很正常。 比如说下面这张表格,很多人就需要将相同项进行合并。 那么这个逆操作又要怎么进行呢?其实也不难...大千世界,无奇不有,我们一方面苦口婆心让人别用合并,取消合并,但还有很多人是需要把数据合并的,这很正常。比如说下面这张表格,很多人就需要将相同项进行合并。那么这个逆操作又要怎么进行呢?其实也不难,有用数据透视表的,也有用分类汇总的,但数据透视表显然不能是首选方式,所以 使用较多的还是这个组合:分类汇总+定位+格式刷就是先对数据分类汇总,在新生成汇总结果的列中,用定位找到空白单元格,并一次性合并,然后移除分类汇总结果,再把合并效果使用格式刷刷到目标区域就完成了。具体过程不详述了,大家可以看下面的操作演示:合并单元格探讨系列主题,欢迎指正:-
如何在合并单元格里保留数据源 -
※ 如何往合并单元格的空单元格里写入数据[BOSS技能] -
如何对合并单元格进行筛选 -
如何统计合并单元格里的数据 -
如何根据首值批量填充空白单元格 -
如何在合并单元格区域汇总数量
[转载请注明出处]
-
-
oracle查询多行数据合并成一行数据
2020-12-18 19:49:13如果是oracle 10g以上 一个wm_concat函数就可以解决。如果是oracle 9i以下就有点麻烦了。表结构如下:NAME Null Type------------------------ --------- -----N_SEC_CODE NOT NULL CHAR(6)C_... -
Excel中跨越合并与合并后居中的区别
2022-04-07 18:06:44不管一次性选择了多少行多少列,只是将列数合并成一个单元格,即每行合并成一个单元格,但原来是多少行还是多少行,并且合并后内容格式与原先相同(下面图例采用的是默认文本型数据左对齐),并不一定是居中。... -
poi 生成word 表格,并向表格单元格中插入多个图片
2019-05-28 10:15:43接这上一篇,导入数据,也要完整导出来。话不多说,直接上代码。 效果图 //根据实体对象 ,生成XWPFDocument public static XWPFDocument exportDataInfoWord(List<DataInfoEntity> list) throws ... -
【excle 如何多行变一行】excel中怎么把多行同一个人的数据变成一行?
2020-12-24 14:48:51excel中怎样实现多行数据变成一行数据最简单的方法就是讲姓名2制(即成员)后在“本人”所,家庭成员1所在列做“选择性粘贴”,然后选择“行列互换”即可。进行上述操作的时候可先将身份证号列删除一下,待粘贴完成后... -
ireport 合并行
2017-08-04 15:09:11我在前面的文章有讲怎么制作简单的二维表格,所以这篇主要是解决表格前面的单元格合并的问题。 这里还要借助子报表,子报表是Jasperreport最为强大的功能,也是最具扩展性的功能组件(纯粹个人意见)。 做... -
将多列单元格中的多个数据拆分为多行数据(explode方法扩展使用)
2020-11-27 12:48:46将多列单元格中的多个数据拆分为多行数据(explode方法扩展使用)1 业务需求2 发现问题3 解决问题实际操作 1 业务需求 在经过昨天梳理通过日期字段提取年月日、timedelta提取时分秒并进行小时汇总后,今天发现业务... -
wps里excel怎么换行在同一单元格内
2020-12-20 14:35:57wps里excel怎么换行在同一单元格内相信很多小伙伴在日常办公中都会用到Excel,在同一个单元格内如何才能进行换行操作呢?方法很简单,下面小编就来为大家介绍。方法一:1. 首先,打开电脑上的Excel。2. 进入后,在... -
全民一起VBA提高篇 第十七回 三原则优化录制代码,一属性玩转合并表格
2019-05-30 08:07:04Worksheet.rows(“2:3”):一次性返回多行 Worksheet.Column(“B:E”): 一次性返回多列 Range.Mergecells: 判断一个单元格是否是完全合并单元格,是返回Ture,否则False,部分合并的单元格则返回Null,表... -
如何将多条update语句合并为一条
2021-01-19 15:39:35需求:如何将多条update语句合并为一条update语句:如,updatetable1setcol='2012'whereid='2014001'updatetable1setcol='1009'whereid='2014003'如何合并为一条?在网上找了好久,总结了一个相对简单的语句(有些... -
如何将多行和多列转换为行和行Excel
2021-09-11 16:49:53如何将多行和多列转换为行和行Excel 来自官方的文档 摘要 使用Microsoft Excel,使用工作表公式OFFSET将跨多行和多列的数据隐藏为数据库格式 (列) 。 详细信息 以下示例将一列中每四行数据转换为单行数据中的四... -
Excel skill: 如何替换换行符,以及如何把一格转换成多行/多列
2021-05-18 08:59:58增加一辅助列,用替换函数替换掉软回车。比如A列是数据,从A1开始,则插入B列,B1输入公式=REPLACE(A1,FIND(CHAR(10),A1),1,"")再用填充柄向下填充。选中B列,复制,选择A1,编辑-选择性粘贴-数值。即将替换后的值... -
Excel的基本操作(二):选择空单元格、复制分类汇总结果、选择性粘贴、辅助列等操作
2020-09-02 08:02:26数据验证-多行变一行9.圈释无效数据10.快速填充11.汉字中提取数字12.分列-源数据13.数据整理14.合并计算 Excel基本操作(二) 1.选择空单元格 需求:将所有空格填充100 步骤:开始--》查找/选择--》定位条件-... -
Excel如何一次性将多行多列表格颠倒行顺序
2021-09-07 21:39:39今天跟大家分享一下Excel如何一次性将多行多列表格颠倒行顺序 1.如下图我们想要将表格数据上下倒置 2.首先我们选中表格单元格区域 3.点击下图选项(Excel工具箱,百度即可了解详细下载安装信息... -
extjs多行只读文本框
2021-04-16 03:12:49extjs 动态只读,,extjs动态时间,extjs多行只读文本框在此不做过多停留 9.把 Extjs 的 ComboBox 样式应用到 sele...extjs 目录 序言 Ext 发展史 什么是 EXT ExtJs UI Engine 简介 Ajax 主流框架与 ExtJS Ext 学习及... -
excel单元格斜线_个人永久性免费-Excel催化剂功能第74波-批量排版格式利器,瞬间美化表格...
2020-10-24 18:46:33PPT和WORD的世界,充满着排版的美化操作,在Excel世界同样也需要对表格、图表的美化,此篇带你进入真正的制表专家行列,使用Excel催化...其控制的颗粒度达到单元格级别,就如一张大画布,横竖画上格子线,任意发挥,... -
latex大括号 多行公式_使用数组公式一步搞定公式批量计算,让效率提高数十倍...
2020-11-15 16:48:28Excel 中数组公式非常有用, 可建立产生多值或对一组值而不是单个值进行操作的公式。掌握数组公式的相关技能技巧, 当在不能使用工作表函数直接得到结果, 又需要对一组或多组数据进行多重计算时,方可大显身手。... -
easyExcel 下载、填充(多列表自动扩充行>、合并策略)
2021-10-26 18:40:24不能一次性就行合并,会出现错乱(怀疑是并行的问题导致,暂时没找到原因) 8、合并单元格时,单个的单元格不能合并,不然会报错-考虑这种情况并去除; 参考: easyexcel/API.md at master · alibaba/easyexcel ·... -
个人永久性免费-Excel催化剂功能第73波-数据转换:单行多项目转多行单项目
2019-07-22 11:17:00如何让这个过程可以更加轻松一点,是Excel催化剂为大家所想的,今天带来一大刚需的数据转换功能,将多个项目列转多行单项目。 业务场景 在一些系统导出的数据里,或者一些表单采集到的多选项目的数据,很常见到... -
个人永久性免费-Excel催化剂功能第100波-透视多行数据为多列数据结构
2019-09-26 00:29:05在数据处理过程中,大量的非预期格式结构需要作转换,有大家熟知的多维转一维(准确来说应该是交叉表结构的数据转二维表标准数据表结构),也同样有一些需要透视操作的数据源,此篇同样提供更便捷的方法实现此类数据... -
一篇文章搞定Java处理Excel表格的各种疑难杂症
2020-05-15 20:54:44设置单元格边框样式 设置单元格的属性 单元格填充 合并单元格 自定义字体样式 特殊设置 sheet放大或缩小 冻结窗口 切割窗口 添加图片 调整列宽适应内容 读取超链接内容 创建超链接 限制单元格的输入值 方式一 ... -
C#开发实战1200例(第一卷+第二卷)+源码下载地址.txt
2019-05-17 09:24:24实例014 快速对多行代码进行注释 17 实例015 使用“///”标记给代码段添加说明 18 2.2 运算符的使用 20 实例016 使用引号运算符进行赋值 20 实例017 使用算术运算符开发简单计算器 21 实例018 使用... -
个人永久性免费-Excel催化剂功能第81波-指定单元格区域内容及公式填充
2019-09-26 00:27:06可以一次性选择多行多列的数据区域 选择待填充数据源 步骤2:点击【按列填充公式】即可完成 程序运算原理为,按行/列的顺序去查找当前单元格的所在行/列的区域,找到第1次出现公式的单元格,将其公式... -
Excel实战之单元格合并与拆分
2022-04-23 10:21:57Excel实战之单元格合并与拆分 -
一、Excel基础操作
2019-02-22 19:18:00一、基本知识 先来认清楚什么是工作簿工作表单元格 很显然,工作簿由工作表组成,工作表有单元格组成,单元格当然是拿来填数据 1.工作簿的属性 工作簿就是Excel文档,扩展名就是xlsx或者还有其他属性 点击...