582 lines
22 KiB
C#
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
|
|
|
|
}
|
|
}
|