using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.ComponentModel; using System.Collections; using System.Reflection; using GZTW.AyaNova.BLL; namespace AyaNova.Plugin.ExportToExcel { /// /// An ExportDatasetAdapter is used to convert data in an object /// or collection into a DataSet /// public class ExportDatasetAdapter { List _columns = new List(); public struct ColumnInfo { internal string name; internal System.Type type; public string ColumnName { get { return name; } } public System.Type ColumnType { get { return type; } } } /// /// Given a data source /// returns an arraylist containing /// ColumnInfo structures /// for each column found /// /// /// public List GetDataSourceColumns(object source) { AutoDiscover(source); return _columns; } /// /// Fills the DataSet with data from an object or collection. /// /// /// The name of the DataTable being filled is will be the class name of /// the object acting as the data source. The /// DataTable will be inserted if it doesn't already exist in the DataSet. /// /// A reference to the DataSet to be filled. /// A reference to the object or collection acting as a data source. public void Fill(DataSet ds, object source,List SelectedItems,LocalizedTextTable LocaleText, string IDField) { mLocaleText = LocaleText; mSelectedItems = SelectedItems; mIDField = IDField; string className = source.GetType().Name; Fill(ds, className, source); } private string mIDField; private LocalizedTextTable mLocaleText = null; private List mSelectedItems = null; /// /// Fills the DataSet with data from an object or collection. /// /// /// /// The name of the DataTable being filled is specified as a parameter. The /// DataTable will be inserted if it doesn't already exist in the DataSet. /// /// A reference to the DataSet to be filled. /// /// A reference to the object or collection acting as a data source. public void Fill(DataSet ds, string tableName, object source) { DataTable dt = ds.Tables[tableName]; bool exists = (dt != null); if (!exists) dt = new DataTable(tableName); Fill(dt, source); if (!exists) ds.Tables.Add(dt); } /// /// Fills a DataTable with data values from an object or collection. /// /// A reference to the DataTable to be filled. /// A reference to the object or collection acting as a data source. public void Fill(DataTable dt, object source) { AutoDiscover(source); DataCopy(dt, source); } #region Data Copy void DataCopy(DataTable dt, object source) { if (source == null) return; if (_columns.Count < 1) return; if (source is IListSource) { System.Diagnostics.Debugger.Break();//unexpected and not coded for DataCopyIList(dt, ((IListSource)source).GetList()); } else { if (source is IList) { DataCopyIList(dt, (IList)source); } else { System.Diagnostics.Debugger.Break();//unexpected and not coded for // they gave us a regular object - create a list ArrayList col = new ArrayList(); col.Add(source); DataCopyIList(dt, (IList)col); } } } void DataCopyIList(DataTable dt, IList ds) { // create columns if needed foreach (ColumnInfo column in _columns) { if (!dt.Columns.Contains(column.name)) dt.Columns.Add(column.name, column.type); } // load the data into the control dt.BeginLoadData(); object o = null; for (int index = 0; index < ds.Count; index++) { bool bFilteredOut=false; DataRow dr = dt.NewRow(); foreach (ColumnInfo column in _columns) { try { if (column.name == "LISTIDFIELD") { //do this instead o = GetFieldObject(ds[index], mIDField); if (o is Guid) { dr[column.name] = (Guid)o; } else if (o is GridNameValueCellItem) { dr[column.name] = ((GridNameValueCellItem)o).Value; } else { System.Diagnostics.Debugger.Break();//should never get here in theory dr[column.name] = Guid.Empty; } if (mSelectedItems.Count() > 0 && (!mSelectedItems.Contains((Guid)dr[column.name]))) { bFilteredOut = true; break; } } else { o = GetFieldObject(ds[index], column.name); if (o == null) { dr[column.name] = o; } else { Type t = o.GetType(); //Make columninfo of the same type with only a few exceptions if (t == typeof(GridNameValueCellItem)) { dr[column.name] = ((GridNameValueCellItem)o).Display; } else if (t == typeof(object)) { //Almost certainly a date time or smartdate object dr[column.name] = o.ToString(); // i.type = typeof(object);//what to do? Emtpy dates can't be used here } else if (t == typeof(GridRelativeTimeCellItem)) { //it's a relative datetime, make it an object dr[column.name] = ((GridRelativeTimeCellItem)o).Display; } else if (t == typeof(Guid)) { //we don't want guid's in the exported stuff so ditch it System.Diagnostics.Debugger.Break();//should never get here in theory continue; } else if (t == typeof(PartSerialPickList)) { System.Text.StringBuilder sb = new StringBuilder(); PartSerialPickList psp = (PartSerialPickList)o; if (psp.Count > 0) { foreach (PartSerialPickList.PartSerialPickListInfo i in psp) { sb.Append(i.SerialNumber); sb.Append("\r\n"); } sb.Length = sb.Length - 2; dr[column.name] = sb.ToString(); } else dr[column.name] = ""; } else dr[column.name] = o; } } } catch (Exception ex) { dr[column.name] = ex.Message; } } if(!bFilteredOut) dt.Rows.Add(dr); } dt.EndLoadData(); } #endregion #region AutoDiscover void AutoDiscover(object source) { object innerSource; if (source is IListSource) { innerSource = ((IListSource)source).GetList(); } else { innerSource = source; } _columns.Clear(); if (innerSource is DataView) { ScanDataView((DataView)innerSource); } else { if (innerSource is IList) { ScanIList((IList)innerSource); } else { // they gave us a regular object ScanObject(innerSource); } } } void ScanDataView(DataView ds) { for (int field = 0; field < ds.Table.Columns.Count; field++) { ColumnInfo i = new ColumnInfo(); i.name = ds.Table.Columns[field].ColumnName; i.type = ds.Table.Columns[field].DataType; _columns.Add(i); } } void ScanIList(IList ds) { if (ds.Count > 0) { // retrieve the first item from the list object obj = ds[0]; if (obj is ValueType && obj.GetType().IsPrimitive) { System.Diagnostics.Debugger.Break();//WHATS UP? // the value is a primitive value type ColumnInfo i = new ColumnInfo(); i.name = "Value"; i.type = obj.GetType(); _columns.Add(i); } else { if (obj is string) { System.Diagnostics.Debugger.Break();//WHATS UP? // the value is a simple string ColumnInfo i = new ColumnInfo(); i.name = "Text"; i.type = typeof(string); _columns.Add(i); } else { // we have a complex Structure or object ScanObject(obj); } } } } void ScanObject(object source) { Type sourceType = source.GetType(); // retrieve a list of all public properties PropertyInfo[] props = sourceType.GetProperties(); for (int column = 0; column < props.Length; column++) if (props[column].CanRead) { ColumnInfo i = new ColumnInfo(); i.name = props[column].Name; if (i.name == mIDField) { //add a new column for the IDField ColumnInfo iID = new ColumnInfo(); iID.name = "LISTIDFIELD"; iID.type = typeof(Guid); _columns.Add(iID); } Type tColumn=props[column].PropertyType; //Make columninfo of the same type with only a few exceptions if (tColumn == typeof(GridNameValueCellItem)) { i.type = typeof(string); } else if (tColumn == typeof(object)) { i.type = typeof(object);//what to do? Emtpy dates can't be used here } else if (tColumn == typeof(GridRelativeTimeCellItem)) { //it's a relative datetime, make it an object i.type = typeof(object); } else if (tColumn == typeof(Guid)) { //we don't want guid's in the exported stuff so ditch it continue; } else if (tColumn == typeof(PartSerialPickList)) { //add a new column for the SerialNumber ColumnInfo iID = new ColumnInfo(); iID.name = i.name; iID.type = typeof(string); _columns.Add(iID); continue; } else i.type = tColumn; _columns.Add(i); } // retrieve a list of all public fields FieldInfo[] fields = sourceType.GetFields(); for (int column = 0; column < fields.Length; column++) { System.Diagnostics.Debugger.Break();//WHATS UP? ColumnInfo i = new ColumnInfo(); i.name = fields[column].Name; i.type = fields[column].FieldType; _columns.Add(i); } } #endregion #region GetFieldObject object GetFieldObject(object obj, string fieldName) { if (obj is DataRowView) { System.Diagnostics.Debugger.Break();//unexpected and not coded for // this is a DataRowView from a DataView return ((DataRowView)obj)[fieldName].ToString(); } else { if (obj is ValueType && obj.GetType().IsPrimitive) { System.Diagnostics.Debugger.Break();//unexpected and not coded for // this is a primitive value type if (obj == null) return string.Empty; else return obj.ToString(); } else { if (obj is string) { System.Diagnostics.Debugger.Break();//unexpected and not coded for // this is a simple string if (obj == null) return string.Empty; else return obj.ToString(); } else { // this is an object or Structure try { Type sourcetype = obj.GetType(); // see if the field is a property PropertyInfo prop = sourcetype.GetProperty(fieldName); if (prop == null || !prop.CanRead) { // no readable property of that name exists - check for a field FieldInfo field = sourcetype.GetField(fieldName); if (field == null) { // no field exists either, throw an exception throw new System.Data.DataException( "NoSuchValueExistsException" + fieldName); } else { // got a field, return its value return field.GetValue(obj); } } else { // found a property, return its value object o = prop.GetValue(obj, null); if (o == null) return null; else return o; } } catch (Exception ex) { throw new System.Data.DataException( "ErrorReadingValueException" + fieldName, ex); } } } } } #endregion #region GetField Original String only version string GetField(object obj, string fieldName) { if (obj is DataRowView) { System.Diagnostics.Debugger.Break();//unexpected and not coded for // this is a DataRowView from a DataView return ((DataRowView)obj)[fieldName].ToString(); } else { if (obj is ValueType && obj.GetType().IsPrimitive) { System.Diagnostics.Debugger.Break();//unexpected and not coded for // this is a primitive value type if (obj == null) return string.Empty; else return obj.ToString(); } else { if (obj is string) { System.Diagnostics.Debugger.Break();//unexpected and not coded for // this is a simple string if (obj == null) return string.Empty; else return obj.ToString(); } else { // this is an object or Structure try { Type sourcetype = obj.GetType(); // see if the field is a property PropertyInfo prop = sourcetype.GetProperty(fieldName); if (prop == null || !prop.CanRead) { // no readable property of that name exists - check for a field FieldInfo field = sourcetype.GetField(fieldName); if (field == null) { // no field exists either, throw an exception throw new System.Data.DataException( "NoSuchValueExistsException" + fieldName); } else { // got a field, return its value return field.GetValue(obj).ToString(); } } else { // found a property, return its value object o= prop.GetValue(obj, null); if(o==null) return ""; else return o.ToString(); } } catch (Exception ex) { throw new System.Data.DataException( "ErrorReadingValueException" + fieldName, ex); } } } } } #endregion } }