先说下会遇到的常见情况:
- 表格可能是个块参照
- 表格的线可能是Polyline
- 会有重叠的线
- 单元格会合并
- 文本会压住单元格
首先提到表格肯定会有个范围,并且线都是两种水平和垂直,文字在单元格内或者文本压住单元格。要解决的难题无非是实际中各种意想不到的情况,这里我无法囊括到所有,只能说包含了大多数情况。
下面开始分析:
- 用户框选“表格”范围,前面提到了在范围内的对象可能是块参照,可能是Polyline,但最终都要转化成Line(两个点一条线的形式),这样才能推测出单元格的位置,哪怕是合并的单元格也要按Line识别处理。
- 想办法在范围内找到水平线和垂直线,构造出最外边的表格线。这里要处理下重叠的线,甚至两平行线间距太小的情况(小于间距认为是一条线)。得到表格的大体轮廓。
- 单元格是有位置的,也就是表格的线也是有顺序的。这里可以用识别到的线,其中水平线按照Y轴排序,垂直线按照X轴排序。
- 表格线的位置确定了,单元格也就确定的。水平1水平2和垂直1垂直2中间的空间就是单元格。
下面是创建的单元格类,没什么特殊的,一个单元格具备的基本数据。
public class TableCell
{
public int RowIndex { set; get; }
public int ColumIndex { set; get; }
public string Value { set; get; }
public MergeRange MergeRange { set; get; }
public bool IsMergeRange { set; get; }
}
/// <summary>
/// 合并单元格的信息
/// </summary>
public class MergeRange
{
/// <summary>
/// 顶部行索引
/// </summary>
public int TopRow;
/// <summary>
/// 底部行索引
/// </summary>
public int BottomRow;
/// <summary>
/// 左边列索引
/// </summary>
public int LeftColumn;
/// <summary>
/// 右边列索引
/// </summary>
public int RightColumn;
}
在判断单元格合并的时候,我是拿单元格和旁边单元格中心点连线,根据判断是否有与之相交对象识别出合并单元格的情况。
double xmid1 = (xList[x] + (xList[x + 1] - xList[x]) / 2);//当前单元格中间x轴位置
double ymid1 = (yList[y] - (yList[y] - yList[y + 1]) / 2);//当前单元格中间y轴位置
Point3d point1 = new Point3d(xmid1, ymid1, 0);
Point3d pointx2 = Point3d.Origin;
if (x + 2 < xList.Count)
{
double xmid2 = (xList[x + 1] + (xList[x + 2] - xList[x + 1]) / 2);
pointx2 = new Point3d(xmid2, ymid1, 0);
PromptSelectionResult crossing = ed.SelectCrossingWindow(point1, pointx2, acSelFtr);
if (crossing.Status == PromptStatus.OK)
{
......
}
}
这次功能展示的代码不多,主要是我代码结构梳理的不够明朗就不展示,直接看下结果吧。