using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using Biff8Excel.Interfaces; namespace Biff8Excel.Formulas { [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)] struct sReferencer1 { [MarshalAs(UnmanagedType.U1, SizeConst = 1)] public byte area; public ushort firstrow; public ushort lastrow; public ushort firstcol; public ushort lastcol; } [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)] struct sReferencer2 { [MarshalAs(UnmanagedType.U1, SizeConst = 1)] public byte area; public ushort externIndex; public ushort firstrow; public ushort lastrow; public ushort firstcol; public ushort lastcol; } public class Referencer { const byte tRef = 0x44; const byte tRef3D = 0x5A; const byte tArea = 0x25; const byte tArea3D = 0x3B; IExternSheet m_externSheet; public Referencer() { } public IExternSheet ExternSheet { set { m_externSheet = value; } } private byte[] WriteAreaNoSheets(string cell1, string cell2) { sReferencer1 reference; reference.area = tArea; reference.firstrow = Globals.ConvertRowStringToNum(cell1); reference.firstcol = Globals.ConvertColStringToNum(cell1); reference.lastrow = Globals.ConvertRowStringToNum(cell2); reference.lastcol = Globals.ConvertColStringToNum(cell2); // not using Absolute positions ("$") character reference.firstcol = (ushort)(reference.firstcol | 0x8000 | 0x4000); reference.lastcol = (ushort)(reference.lastcol | 0x8000 | 0x4000); return Globals.GetStructToBytes(reference); } private byte[] WriteAreaWithSheets(ushort externIndex, string cell1, string cell2) { sReferencer2 reference; reference.area = tArea3D; reference.externIndex = externIndex; reference.firstrow = Globals.ConvertRowStringToNum(cell1); reference.firstcol = Globals.ConvertColStringToNum(cell1); reference.lastrow = Globals.ConvertRowStringToNum(cell2); reference.lastcol = Globals.ConvertColStringToNum(cell2); // not using Absolute positions ("$") character reference.firstcol = (ushort)(reference.firstcol | 0x8000 | 0x4000); reference.lastcol = (ushort)(reference.lastcol | 0x8000 | 0x4000); return Globals.GetStructToBytes(reference); } private byte[] WriteRefNoSheets(string cell) { byte[] b = new byte[5]; ushort row, col; row = Globals.ConvertRowStringToNum(cell); col = Globals.ConvertColStringToNum(cell); // not using Absolute positions ("$") character col = (ushort)((ushort)col | 0x8000 | 0x4000); b[0] = tRef; BitConverter.GetBytes(row).CopyTo(b, 1); BitConverter.GetBytes(col).CopyTo(b, 3); return b; } private byte[] WriteRefWithSheets(ushort externIndex, string cell) { byte[] b = new byte[7]; ushort row, col; row = Globals.ConvertRowStringToNum(cell); col = Globals.ConvertColStringToNum(cell); // not using Absolute positions ("$") character col = (ushort)(col | 0x8000 | 0x4000); b[0] = tRef3D; BitConverter.GetBytes(externIndex).CopyTo(b, 1); BitConverter.GetBytes(row).CopyTo(b, 3); BitConverter.GetBytes(col).CopyTo(b, 5); return b; } public byte[] Serialize(string reference) { string sheet1, sheet2, sheets; string cell1, cell2, cells; string s; int pos; ushort x, idx, token; sheet1 = sheet2 = sheets = ""; cell1 = cell2 = cells = ""; idx = 0; if (reference == null) throw new ArgumentNullException("reference", " not null"); // See if this ref is part of a built in function eg SUM(Sheet1!A1:A2) // we only want the Sheet1!A1:A2 part pos = reference.IndexOf("("); if (pos > -1) { //reference = reference.Substring(pos + 1); //reference = reference.Substring(0, reference.Length - 1); //remove the closing bracket //得到括号中的内容 reference = reference.Substring(pos + 1, reference.Length - 2 - pos); } pos = reference.IndexOf("!"); if (pos > -1) // we have sheet refs { //split out the sheet(s) x = (ushort)(pos - 1); do { s = reference.Substring(x, 1); if (s == "(" || s == "$") break; sheets += s; x--; } while (x > 0); sheets = Globals.StrReverse(sheets); // how many sheets are their pos = (ushort)sheets.IndexOf(":"); if (pos > -1) { sheet1 = sheets.Substring(0, pos - 1); if (sheets.Substring(pos + 1) == "$") sheet2 = sheets.Substring(pos + 2); else sheet2 = sheets.Substring(pos + 1); } else { sheet1 = sheets; sheet2 = sheets; } // Get an index into the Extern Sheet record idx = m_externSheet.AddEntry(sheet1, sheet2); } // get the cell references pos =reference.IndexOf("!"); if (pos > -1) cells = reference.Substring(pos + 1); else cells = reference; // Is it an AreaRef (A1:B1) or CellRef (A1). pos = cells.IndexOf(":"); if (pos > -1) { token = (sheet1.Length == 0 ? tArea : tArea3D); cell1 = cells.Substring(0, pos ); cell2 = cells.Substring(pos + 1); if (token == tArea) return WriteAreaNoSheets(cell1, cell2); else return WriteAreaWithSheets(idx, cell1, cell2); } else { token = (sheet1.Length == 0 ? tRef : tRef3D); cell1 = cells; if (token == tRef) return WriteRefNoSheets(cell1); else return WriteRefWithSheets(idx, cell1); } } } }