using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Xml;
namespace WayGo.ExcelMergeTool.Common
{
public class WayGoTable : System.Data.DataTable
{
private XmlNode _SchemaSheet;
private XmlNode _SheetNode;
private XmlNamespaceManager _nsmgr;
public XmlNode SchemaSheet
{
get
{
return this._SchemaSheet;
}
set
{
this._SchemaSheet = value;
}
}
public XmlNode SheetNode
{
get
{
return this._SheetNode;
}
set
{
this._SheetNode = value;
}
}
public XmlNamespaceManager nsmgr
{
get
{
return this._nsmgr;
}
set
{
this._nsmgr = value;
}
}
public WayGoTable(XmlNode sheetNode,XmlNode schemaSheet,XmlNamespaceManager ns):base()
{
this.Columns.Add("ID", typeof(System.String));
this.Columns.Add("StartRow", typeof(System.Int16));
this.Columns.Add("EndRow", typeof(System.Int16));
this.Columns.Add("StartCol", typeof(System.Int16));
this.Columns.Add("EndCol", typeof(System.Int16));
this.Columns.Add("Method", typeof(System.String));
this._SchemaSheet = schemaSheet;
this._SheetNode = sheetNode;
this._nsmgr = ns;
this.Initial();
this.sort();
}
public WayGoTable() : base()
{
}
/// <summary>
/// 添加一行
/// </summary>
/// <param name="ID"></param>
/// <param name="startRow"></param>
/// <param name="endRow"></param>
/// <param name="startCol"></param>
/// <param name="endCol"></param>
/// <param name="method"></param>
private void addRow(string ID, int startRow, int endRow, int startCol, int endCol, MergeMethod method)
{
DataRow r = this.NewRow();
r["ID"] = ID;
r["StartRow"] = startRow;
r["EndRow"] = endRow;
r["StartCol"] = startCol;
r["EndCol"] = endCol;
r["Method"] = method;
this.Rows.Add(r);
}
/// <summary>
/// 根据 Schema和Sheet File的Sheet节点 初始化表格
/// </summary>
/// <param name="schemaSheet"></param>
/// <param name="sheetNode"></param>
private void Initial()
{
string ID,startRefValue;
MergeMethod method;
int startRow, endRow, startCol, endCol;
int find;
int row,col,repeat;
int rowoffset, rowend;
int coloffset,colend;
XmlNodeList colNodes;
XmlNode Item;
rowend = 0;
startRow = 0;
endRow = 0;
#region 遍历Schema中Sheet的子节点
foreach (XmlNode node in SchemaSheet.ChildNodes)
{
method = SchemaNode.Instance.getNodeName(node.Name);
if(method == MergeMethod.AddInString)
{
continue;
}
ID = node.Attributes["id"].Value.ToString();
col = Convert.ToInt16(node.SelectSingleNode(SchemaNode.StartRefColumn).InnerText);
Item = node.SelectSingleNode("Item");
repeat = Convert.ToInt16(node.SelectSingleNode(SchemaNode.StartRefRepeat).InnerText);
rowoffset = Convert.ToInt16(Item.Attributes["rowoffset"].Value);
coloffset = Convert.ToInt16(Item.Attributes["coloffset"].Value);
colend = Convert.ToInt16(Item.Attributes["colend"].Value);
startCol = col + coloffset;
endCol = col + colend;
if (method == MergeMethod.Add)
{
rowend = Convert.ToInt16(Item.Attributes["rowend"].Value);
}
startRefValue = node.SelectSingleNode(SchemaNode.StartRefValue).InnerText;
colNodes = SheetNode.SelectNodes("Table/Row/Cell[@ss:Index=" + col + "]", nsmgr);
find = 0;
#region Col Node ----
foreach (XmlNode n in colNodes)
{
row = Convert.ToInt16(n.ParentNode.Attributes["ss:Index"].Value);
if (!string.IsNullOrEmpty(n.InnerText) && n.InnerText == startRefValue && !isExistsMergeArea(row,col))
{
find++;
if (find == repeat)
{
startRow = row + rowoffset;
if (method == MergeMethod.Add)
{
endRow = row + rowend;
}
this.addRow(ID, startRow, endRow, startCol, endCol, method);
break;
}
}
}
#endregion
}
#endregion
}
/// <summary>
/// 排序
/// </summary>
private void sort()
{
if (this.Rows.Count < 2)
{
return;
}
DataRow[] rows = this.Select("", "StartRow");
DataTable t = this.Clone();
t.Clear();
foreach (DataRow row in rows)
{
t.ImportRow(row);
}
this.Clear();
foreach (DataRow row in t.Rows)
{
this.ImportRow(row);
}
}
/// <summary>
/// 判断某个单元格是否位于其他合并区域中
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
/// <returns></returns>
private bool isExistsMergeArea(int row,int col)
{
foreach (DataRow r in this.Rows)
{
if (Convert.ToInt16(r["StartRow"]) <= row &&
Convert.ToInt16(r["EndRow"]) >= row &&
Convert.ToInt16(r["StartCol"]) <= col &&
Convert.ToInt16(r["EndCol"]) >= col)
{
return true;
}
}
return false;
}
/// <summary>
/// 判断某个单元格是否位于其他合并区域中
/// </summary>
/// <param name="row"></param>
/// <param name="col"></param>
/// <param name="rowIndex"></param>
/// <returns></returns>
private bool isExistsMergeArea(int row, int col, int rowIndex)
{
for (int i = 0; i < rowIndex; i++)
{
if (Convert.ToInt16(this.Rows[i]["StartRow"]) <= row &&
Convert.ToInt16(this.Rows[i]["EndRow"]) >= row &&
Convert.ToInt16(this.Rows[i]["StartCol"]) <= col &&
Convert.ToInt16(this.Rows[i]["EndCol"]) >= col)
{
return true;
}
}
return false;
}
/// <summary>
/// 修复合并当前行以下的行
/// </summary>
/// <param name="row"></param>
/// <param name="rowIndex"></param>
public void Repair(DataRow row,int rowIndex)
{
int rowI, find, startRow, repeat, rowoffset;
find = 0;
DataRow[] r = this.Select("ID=" + row["ID"].ToString());
XmlNode node,Item;
if (row["Method"].ToString() == MergeMethod.Add.ToString())
{
node = this.SchemaSheet.SelectSingleNode(SchemaNode.Add + "[@id='" + row["ID"].ToString() + "']");
}
else
{
node = this.SchemaSheet.SelectSingleNode(SchemaNode.Append + "[@id='" + row["ID"].ToString() + "']");
}
Item = node.SelectSingleNode("Item");
int col = Convert.ToInt16(node.SelectSingleNode(SchemaNode.StartRefColumn).InnerText);
string startRefValue = node.SelectSingleNode(SchemaNode.StartRefValue).InnerText;
repeat = Convert.ToInt16(node.SelectSingleNode(SchemaNode.StartRefRepeat).InnerText);
rowoffset = Convert.ToInt16(Item.Attributes["rowoffset"].Value);
XmlNodeList colNodes = SheetNode.SelectNodes("Table/Row/Cell[@ss:Index=" + col + "]", nsmgr);
#region Col Node ----
foreach (XmlNode n in colNodes)
{
rowI = Convert.ToInt16(n.ParentNode.Attributes["ss:Index"].Value);
if (!string.IsNullOrEmpty(n.InnerText) && n.InnerText == startRefValue && !isExistsMergeArea(rowI, col, rowIndex))
{
find++;
if (find == repeat)
{
startRow = rowI + rowoffset;
//如果该行是正确的,则不继续修复,退出程序
if(startRow == Convert.ToInt16(row["StartRow"]))
{
return;
}
else
{
//如果该行的起始行错误,则修正该行后重新排序,并继续修复处于该行的位置的行
r[0]["StartRow"] = startRow;
this.sort();
this.Repair(this.Rows[rowIndex], rowIndex);
}
}
}
}
#endregion
}
}
}