Files
2018-06-29 19:47:36 +00:00

582 lines
22 KiB
C#

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
{
/// <summary>
/// An ExportDatasetAdapter is used to convert data in an object
/// or collection into a DataSet
/// </summary>
public class ExportDatasetAdapter
{
List<ColumnInfo> _columns = new List<ColumnInfo>();
public struct ColumnInfo
{
internal string name;
internal System.Type type;
public string ColumnName
{
get
{
return name;
}
}
public System.Type ColumnType
{
get { return type; }
}
}
/// <summary>
/// Given a data source
/// returns an arraylist containing
/// ColumnInfo structures
/// for each column found
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public List<ColumnInfo> GetDataSourceColumns(object source)
{
AutoDiscover(source);
return _columns;
}
/// <summary>
/// Fills the DataSet with data from an object or collection.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
/// <param name="ds">A reference to the DataSet to be filled.</param>
/// <param name="source">A reference to the object or collection acting as a data source.</param>
public void Fill(DataSet ds, object source,List<Guid> 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<Guid> mSelectedItems = null;
/// <summary>
/// Fills the DataSet with data from an object or collection.
///
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
/// <param name="ds">A reference to the DataSet to be filled.</param>
/// <param name="tableName"></param>
/// <param name="source">A reference to the object or collection acting as a data source.</param>
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);
}
/// <summary>
/// Fills a DataTable with data values from an object or collection.
/// </summary>
/// <param name="dt">A reference to the DataTable to be filled.</param>
/// <param name="source">A reference to the object or collection acting as a data source.</param>
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
}
}