BusinessMgr web apps
This commit is contained in:
@@ -4,7 +4,6 @@ using Sarand.Net.Standard.Accounts.QuickBooks.Dbas;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Internal;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Xml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
@@ -45,6 +45,13 @@ namespace Sarand.Net.Standard.Base.Interfaces
|
||||
protected SaInterfaceConsole ()
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
@@ -31,6 +31,13 @@ namespace Sarand.Net.Standard.Base.ItemOptions
|
||||
protected SaItemOptionConsole ()
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ namespace Sarand.Net.Standard.Base.Procs
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
public abstract class SacsProcess : SacsDisposable
|
||||
public abstract class SaProcess_Base : SacsDisposable
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Process options and groups - for configuration of process to run.
|
||||
@@ -81,7 +81,7 @@ namespace Sarand.Net.Standard.Base.Procs
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SacsProcess (Config config)
|
||||
protected SaProcess_Base (Config config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
+2
-2
@@ -5,7 +5,7 @@ using Sarand.Net.Standard.Base.Bus;
|
||||
namespace Sarand.Net.Standard.Base.Procs
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SacsReport : SaErrorStateItem
|
||||
public abstract class SaReport_Base : SaErrorStateItem
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
@@ -22,7 +22,7 @@ namespace Sarand.Net.Standard.Base.Procs
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SacsReport (Config config)
|
||||
protected SaReport_Base (Config config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
@@ -154,6 +154,13 @@ namespace Sarand.Net.Standard.Base.ReferenceData
|
||||
protected SaReferenceDataConsole()
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
@@ -78,6 +78,13 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
protected SaSecurityConsole()
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
@@ -252,6 +259,8 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
{
|
||||
return GetSecurityItemByCode(SaSecurity.ItemType.User, code);
|
||||
}
|
||||
public abstract SaSecurityItem GetUserByEmail(String emailAddress);
|
||||
public abstract SaSecurityItem GetSecurityItemById(SaSecurity.ItemType securityItemType, SysId id);
|
||||
public abstract SaSecurityItem GetSecurityItemByCode(SaSecurity.ItemType securityItemType, String code);
|
||||
public abstract SaSecurityItem GetSecurityItem(SaSecurityItem.Params prm);
|
||||
// Security item properties.
|
||||
@@ -270,6 +279,7 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
// Security item updates.
|
||||
public abstract bool CreateUser(String code, String name, DbUpdateInfo dbUpdateInfo);
|
||||
public abstract bool AssignUserToGroup(String userCode, String groupCode, DbUpdateInfo dbUpdateInfo);
|
||||
public abstract bool UpdateSecurityItem(SaSecurityItem securityItem, DbUpdateInfo dbUpdateInfo);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// S e c u r i t y I t e m s L i n k s
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Text;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Standard.Base.Security
|
||||
{
|
||||
@@ -45,11 +46,18 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
public String EmailAddress { get; set; } = String.Empty;
|
||||
public String Description { get; set; } = String.Empty;
|
||||
public String Location { get; set; } = String.Empty;
|
||||
public int DataItemType { get; set; } = -1;
|
||||
// Security.
|
||||
public String PasswordEncrypted { get; set; } = String.Empty;
|
||||
public String PasswordSalt { get; set; } = String.Empty;
|
||||
public String PasswordHash { get; set; } = String.Empty;
|
||||
public List<String> PasswordHistory { get; } = new List<string>();
|
||||
public String PasswordToken { get; set; } = String.Empty;
|
||||
public DateTime PasswordChangedAt { get; set; } = DateTime.MinValue;
|
||||
// Login.
|
||||
public DateTime LastLogin { get; set; } = DateTime.MinValue;
|
||||
public int DataItemType { get; set; } = -1;
|
||||
public DateTime LastInvalidLoginAt { get; set; } = DateTime.MinValue;
|
||||
public short InvalidLoginCount { get; set; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -89,6 +97,12 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
get { return data.Location; }
|
||||
set { CheckChanged(data.Location, value); data.Location = value; }
|
||||
}
|
||||
public int DataItemType
|
||||
{
|
||||
get { return data.DataItemType; }
|
||||
set { CheckChanged(data.DataItemType, value); data.DataItemType = value; }
|
||||
}
|
||||
// Security.
|
||||
public String PasswordEncrypted
|
||||
{
|
||||
get { return data.PasswordEncrypted; }
|
||||
@@ -104,15 +118,41 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
get { return data.PasswordHash; }
|
||||
set { CheckChanged(data.PasswordHash, value); data.PasswordHash = value; }
|
||||
}
|
||||
public List<String> PasswordHistory
|
||||
{
|
||||
get { return data.PasswordHistory; }
|
||||
set
|
||||
{
|
||||
CheckChanged(data.PasswordHistory, value);
|
||||
data.PasswordHistory.Clear();
|
||||
data.PasswordHistory.AddRange((value ?? new List<String>()).FindAll(item => !StringUtil.IsEmpty(StringUtil.TrimAll(item))));
|
||||
}
|
||||
}
|
||||
public String PasswordToken
|
||||
{
|
||||
get { return data.PasswordToken; }
|
||||
set { CheckChanged(data.PasswordToken, value); data.PasswordToken = value; }
|
||||
}
|
||||
public DateTime PasswordChangedAt
|
||||
{
|
||||
get { return data.PasswordChangedAt; }
|
||||
set { CheckChanged(data.PasswordChangedAt, value); data.PasswordChangedAt = value; }
|
||||
}
|
||||
// Login.
|
||||
public DateTime LastLogin
|
||||
{
|
||||
get { return data.LastLogin; }
|
||||
set { CheckChanged(data.LastLogin, value); data.LastLogin = value; }
|
||||
}
|
||||
public int DataItemType
|
||||
public DateTime LastInvalidLoginAt
|
||||
{
|
||||
get { return data.DataItemType; }
|
||||
set { CheckChanged(data.DataItemType, value); data.DataItemType = value; }
|
||||
get { return data.LastInvalidLoginAt; }
|
||||
set { CheckChanged(data.LastInvalidLoginAt, value); data.LastInvalidLoginAt = value; }
|
||||
}
|
||||
public short InvalidLoginCount
|
||||
{
|
||||
get { return data.InvalidLoginCount; }
|
||||
set { CheckChanged(data.InvalidLoginCount, value); data.InvalidLoginCount = value; }
|
||||
}
|
||||
// Flags.
|
||||
public bool AuthenticatedUser
|
||||
@@ -128,11 +168,18 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
EmailAddress = data.EmailAddress;
|
||||
Description = data.Description;
|
||||
Location = data.Location;
|
||||
DataItemType = data.DataItemType;
|
||||
// Security.
|
||||
PasswordEncrypted = data.PasswordEncrypted;
|
||||
PasswordSalt = data.PasswordSalt;
|
||||
PasswordHash = data.PasswordHash;
|
||||
PasswordHistory = data.PasswordHistory;
|
||||
PasswordToken = data.PasswordToken;
|
||||
PasswordChangedAt = data.PasswordChangedAt;
|
||||
// Login.
|
||||
LastLogin = data.LastLogin;
|
||||
DataItemType = data.DataItemType;
|
||||
LastInvalidLoginAt = data.LastInvalidLoginAt;
|
||||
InvalidLoginCount = data.InvalidLoginCount;
|
||||
base.PopulateFrom(data);
|
||||
}
|
||||
public Data Clone ()
|
||||
@@ -153,7 +200,15 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
public ValidValue EmailAddress { get; set; } = ValidValue.Valid;
|
||||
public ValidValue Description { get; set; } = ValidValue.Valid;
|
||||
public ValidValue Location { get; set; } = ValidValue.Valid;
|
||||
// Security.
|
||||
public ValidValue Password { get; set; } = ValidValue.Valid;
|
||||
public ValidValue PasswordHistory { get; set; } = ValidValue.Valid;
|
||||
public ValidValue PasswordToken { get; set; } = ValidValue.Valid;
|
||||
public ValidValue PasswordChanged { get; set; } = ValidValue.Valid;
|
||||
// Login.
|
||||
public ValidValue LastLogin { get; set; } = ValidValue.Valid;
|
||||
public ValidValue LastInvalidLogin { get; set; } = ValidValue.Valid;
|
||||
public ValidValue InvalidLoginCount { get; set; } = ValidValue.Valid;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -239,6 +294,14 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
get { return data.Location; }
|
||||
set { data.Location = value; }
|
||||
}
|
||||
public int DataItemType
|
||||
{
|
||||
get { return data.DataItemType; }
|
||||
set { data.DataItemType = value; }
|
||||
}
|
||||
|
||||
// Security.
|
||||
[Obsolete("Avoid using the original C++ password encryption - switch to hashed password instead.")]
|
||||
public String PasswordEncrypted
|
||||
{
|
||||
get { return data.PasswordEncrypted; }
|
||||
@@ -254,15 +317,37 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
get { return data.PasswordHash; }
|
||||
set { data.PasswordHash = value; }
|
||||
}
|
||||
public List<String> PasswordHistory
|
||||
{
|
||||
get { return data.PasswordHistory; }
|
||||
set { data.PasswordHistory = value; }
|
||||
}
|
||||
public String PasswordToken
|
||||
{
|
||||
get { return data.PasswordToken; }
|
||||
set { data.PasswordToken = value; }
|
||||
}
|
||||
public DateTime PasswordChangedAt
|
||||
{
|
||||
get { return data.PasswordChangedAt; }
|
||||
set { data.PasswordChangedAt = value; }
|
||||
}
|
||||
|
||||
// Login.
|
||||
public DateTime LastLogin
|
||||
{
|
||||
get { return data.LastLogin; }
|
||||
set { data.LastLogin = value; }
|
||||
}
|
||||
public int DataItemType
|
||||
public DateTime LastInvalidLoginAt
|
||||
{
|
||||
get { return data.DataItemType; }
|
||||
set { data.DataItemType = value; }
|
||||
get { return data.LastInvalidLoginAt; }
|
||||
set { data.LastInvalidLoginAt = value; }
|
||||
}
|
||||
public short InvalidLoginCount
|
||||
{
|
||||
get { return data.InvalidLoginCount; }
|
||||
set { data.InvalidLoginCount = value; }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace Sarand.Net.Standard.Base.Security
|
||||
public abstract bool SecurityItemExistsById (SysId id);
|
||||
public abstract bool SecurityItemExistsByTypeCode (SaSecurity.ItemType securityItemType, String code);
|
||||
public abstract SaSecurityItem GetSecurityItemById (SysId id);
|
||||
public abstract SaSecurityItem GetSecurityItemByTypeId(SaSecurity.ItemType securityItemType, SysId id);
|
||||
public abstract SaSecurityItem GetSecurityItemByTypeEmail(SaSecurity.ItemType securityItemType, String emailAddress);
|
||||
public abstract SaSecurityItem GetSecurityItemByTypeCode(SaSecurity.ItemType securityItemType, String code);
|
||||
public abstract SaSecurityItem GetSecurityItem (SaSecurityItem.Params prmSecItem);
|
||||
|
||||
|
||||
@@ -28,6 +28,13 @@ namespace Sarand.Net.Standard.Base.UpdateLog
|
||||
protected SaUpdateLogConsole ()
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
@@ -29,6 +29,14 @@ namespace Sarand.Net.Standard.Dbas.Interfaces
|
||||
Database = database;
|
||||
interfaceMgr = new SaInterfaceMgr_Dbas(this);
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (interfaceMgr != null) interfaceMgr.Dispose(); interfaceMgr = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
@@ -29,6 +29,14 @@ namespace Sarand.Net.Standard.Dbas.ItemOptions
|
||||
Database = database;
|
||||
itemOptionMgr = new SaItemOptionMgr_Dbas(this);
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (itemOptionMgr != null) itemOptionMgr.Dispose(); itemOptionMgr = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
@@ -13,11 +13,11 @@ using System.Threading.Tasks;
|
||||
namespace Sarand.Net.Standard.Dbas.Proc
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaDbProcess_CompareDatabaseSchemas : SacsProcess
|
||||
public class SaDbProcess_CompareDatabaseSchemas : SaProcess_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Configuration.
|
||||
public new class Config : SacsProcess.Config
|
||||
public new class Config : SaProcess_Base.Config
|
||||
{
|
||||
public Config(ISacsDatabase sourceDatabase, ISacsDatabase targetDatabase)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ using System.Threading.Tasks;
|
||||
namespace Sarand.Net.Standard.Dbas.Proc
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaDbProcess_ConvertDbDefinition : SacsProcess
|
||||
public class SaDbProcess_ConvertDbDefinition : SaProcess_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Configuration.
|
||||
@@ -30,7 +30,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
||||
Unknown = 0,
|
||||
CsCode
|
||||
}
|
||||
public new class Config : SacsProcess.Config
|
||||
public new class Config : SaProcess_Base.Config
|
||||
{
|
||||
public Config ()
|
||||
{
|
||||
|
||||
@@ -17,11 +17,11 @@ using System.Xml.Linq;
|
||||
namespace Sarand.Net.Standard.Dbas.Proc
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaDbProcess_ConvertDbSchema : SacsProcess
|
||||
public class SaDbProcess_ConvertDbSchema : SaProcess_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Configuration.
|
||||
public new class Config : SacsProcess.Config
|
||||
public new class Config : SaProcess_Base.Config
|
||||
{
|
||||
public Config()
|
||||
{
|
||||
|
||||
@@ -28,6 +28,13 @@ namespace Sarand.Net.Standard.Dbas.ReferenceData
|
||||
Database = database;
|
||||
referenceDataMgr = new SaReferenceDataMgr_Dbas(this);
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
@@ -26,6 +26,14 @@ namespace Sarand.Net.Standard.Dbas.Security
|
||||
// Initialise security manager.
|
||||
securityMgr = new SaSecurityMgr_Dbas(this);
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (securityMgr != null) securityMgr.Dispose(); securityMgr = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Database properties.
|
||||
@@ -364,6 +372,14 @@ namespace Sarand.Net.Standard.Dbas.Security
|
||||
//-------------------------------------------------------------------
|
||||
// S e c u r i t y I t e m s
|
||||
//-------------------------------------------------------------------
|
||||
public override SaSecurityItem GetUserByEmail(String emailAddress)
|
||||
{
|
||||
return securityMgr.GetSecurityItemByTypeEmail(SaSecurity.ItemType.User, emailAddress);
|
||||
}
|
||||
public override SaSecurityItem GetSecurityItemById(SaSecurity.ItemType securityItemType, SysId id)
|
||||
{
|
||||
return securityMgr.GetSecurityItemByTypeId(securityItemType, id);
|
||||
}
|
||||
public override SaSecurityItem GetSecurityItemByCode(SaSecurity.ItemType securityItemType, string code)
|
||||
{
|
||||
return securityMgr.GetSecurityItemByTypeCode(securityItemType, code);
|
||||
@@ -529,6 +545,13 @@ namespace Sarand.Net.Standard.Dbas.Security
|
||||
ClearErrorState();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public override bool UpdateSecurityItem(SaSecurityItem securityItem, DbUpdateInfo dbUpdateInfo)
|
||||
{
|
||||
ClearErrorState();
|
||||
if (!securityMgr.UpdateSecurityItem(securityItem, dbUpdateInfo))
|
||||
return SetErrorState(securityMgr.ErrorStateMessage);
|
||||
return !HasErrorState();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Security Item list.
|
||||
|
||||
@@ -99,6 +99,26 @@ namespace Sarand.Net.Standard.Dbas.Security
|
||||
prmSecItem.StatusCat = SaSecurityItem.StatusCat.Any;
|
||||
return GetSecurityItem(GetSecurityItemQueryFilter(prmSecItem).Concat(" AND ", "(", ")"));
|
||||
}
|
||||
public override SaSecurityItem GetSecurityItemByTypeId(SaSecurity.ItemType securityItemType, SysId id)
|
||||
{
|
||||
ClearErrorState();
|
||||
if ((int)securityItemType < 1 || !SysId.IsValid(id)) return null;
|
||||
SaSecurityItem.Params prmSecItem = new SaSecurityItem.Params();
|
||||
prmSecItem.IncludedIds.Add(id);
|
||||
prmSecItem.SecurityItemType = securityItemType;
|
||||
prmSecItem.StatusCat = SaSecurityItem.StatusCat.Any;
|
||||
return GetSecurityItem(GetSecurityItemQueryFilter(prmSecItem).Concat(" AND ", "(", ")"));
|
||||
}
|
||||
public override SaSecurityItem GetSecurityItemByTypeEmail(SaSecurity.ItemType securityItemType, string emailAddress)
|
||||
{
|
||||
ClearErrorState();
|
||||
if ((int)securityItemType < 1 || StringUtil.IsEmpty(emailAddress)) return null;
|
||||
SaSecurityItem.Params prmSecItem = new SaSecurityItem.Params();
|
||||
prmSecItem.SecurityItemType = securityItemType;
|
||||
prmSecItem.EmailAddress = emailAddress;
|
||||
prmSecItem.StatusCat = SaSecurityItem.StatusCat.Any;
|
||||
return GetSecurityItem(GetSecurityItemQueryFilter(prmSecItem).Concat(" AND ", "(", ")"));
|
||||
}
|
||||
public override SaSecurityItem GetSecurityItemByTypeCode(SaSecurity.ItemType securityItemType, string code)
|
||||
{
|
||||
ClearErrorState();
|
||||
|
||||
@@ -27,6 +27,14 @@ namespace Sarand.Net.Standard.Dbas.UpdateLog
|
||||
Database = database;
|
||||
updateLogMgr = new SaUpdateLogMgr_Dbas(this);
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (updateLogMgr != null) updateLogMgr.Dispose(); updateLogMgr = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Excel
|
||||
namespace Sarand.Net.Standard.Proc.Excel
|
||||
{
|
||||
//=======================================================================
|
||||
// MS Excel constant definitions.
|
||||
+1
-1
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Excel
|
||||
namespace Sarand.Net.Standard.Proc.Excel
|
||||
{
|
||||
//=======================================================================
|
||||
// Definitions.
|
||||
+1
-1
@@ -5,7 +5,7 @@ using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Excel
|
||||
namespace Sarand.Net.Standard.Proc.Excel
|
||||
{
|
||||
//=======================================================================
|
||||
// Some Excel enumerated values are replaced with local integers or
|
||||
+3
-3
@@ -9,10 +9,10 @@ using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Data.Xml;
|
||||
using Sarand.Net.Standard.Data.Zip;
|
||||
using Sarand.Net.Standard.Proc.Xml;
|
||||
using Sarand.Net.Standard.Proc.Zip;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Excel
|
||||
namespace Sarand.Net.Standard.Proc.Excel
|
||||
{
|
||||
//=======================================================================
|
||||
/// <summary>Style properties retrieved directly from spreadsheet xml data.</summary>
|
||||
+1
-1
@@ -11,7 +11,7 @@ using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Excel
|
||||
namespace Sarand.Net.Standard.Proc.Excel
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaMsSpreadsheet_OpenXml : SaMsSpreadsheet
|
||||
@@ -0,0 +1,887 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Sarand.Net.Standard.Proc.Xml;
|
||||
using Sarand.Net.Standard.Proc.Zip;
|
||||
|
||||
namespace Sarand.Net.Standard.Proc.Excel
|
||||
{
|
||||
|
||||
//=======================================================================
|
||||
/// <summary>Excel spreadsheet read directly from xml data rather than via COM/Interop.</summary>
|
||||
public class SaMsSpreadsheet_POI : SaMsSpreadsheet
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
internal class Workbook
|
||||
{
|
||||
internal SaMsZipArchive WorkbookArchive { get; set; }
|
||||
internal SaMsXmlDocument WorkbookDoc { get; set; }
|
||||
internal SaMsXmlDocument SharedStringsDoc { get; set; }
|
||||
internal SaMsXmlDocument StylesDoc { get; set; }
|
||||
internal uint WorksheetCount { get; set; }
|
||||
internal uint ActiveSheetPos { get; set; }
|
||||
internal bool IsValid () { return (WorkbookDoc != null && WorkbookDoc.GetRootElement() != null); }
|
||||
}
|
||||
private Workbook workbook;
|
||||
private class Worksheet
|
||||
{
|
||||
internal uint WorksheetPos { get; set; }
|
||||
internal uint WorksheetId { get; set; }
|
||||
internal String WorksheetArchivePath { get; set; }
|
||||
internal String WorksheetName { get; set; }
|
||||
internal SaMsXmlDocument WorksheetDoc { get; set; }
|
||||
internal uint ActiveColPos { get; set; }
|
||||
internal uint ActiveRowPos { get; set; }
|
||||
internal class NodesData
|
||||
{
|
||||
internal SaMsXmlElement Cols { get; set; }
|
||||
internal SaMsXmlElement ActiveCol { get; set; }
|
||||
internal SaMsXmlElement Rows { get; set; }
|
||||
internal SaMsXmlElement ActiveRow { get; set; }
|
||||
}
|
||||
internal NodesData Nodes { get; } = new NodesData();
|
||||
bool IsValid () { return (WorksheetDoc != null && WorksheetDoc.GetRootElement() != null); }
|
||||
|
||||
}
|
||||
private Worksheet worksheet;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaMsSpreadsheet_POI () : base()
|
||||
{
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
CloseWorkbook();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// W o r k b o o k
|
||||
//-------------------------------------------------------------------
|
||||
public override bool IsWorkbookValid ()
|
||||
{
|
||||
return (workbook != null && workbook.IsValid());
|
||||
}
|
||||
public override bool CreateWorkbook ()
|
||||
{
|
||||
CloseWorkbook();
|
||||
ClearErrorState();
|
||||
|
||||
// Create new workbook.
|
||||
workbook = new Workbook();
|
||||
workbook.WorkbookArchive = new SaMsZipArchive();
|
||||
workbook.SharedStringsDoc = new SaMsXmlDocument();
|
||||
workbook.StylesDoc = new SaMsXmlDocument();
|
||||
|
||||
return SetErrorState("Creating workbook not supported");
|
||||
}
|
||||
public override bool OpenWorkbook (String filePath)
|
||||
{
|
||||
CloseWorkbook();
|
||||
ClearErrorState();
|
||||
if (!File.Exists(filePath))
|
||||
return SetErrorState("Workbook not found");
|
||||
List<String> validExtensions = new List<string>() { /*".xls",*/ ".xlsx", ".xlsb", ".zip" };
|
||||
String extension = Path.GetExtension(filePath);
|
||||
if (!validExtensions.ContainsCI(Path.GetExtension(filePath)))
|
||||
return SetErrorState("Invalid document type (expected xlsx/xlsb)");
|
||||
|
||||
try
|
||||
{
|
||||
// Open workbook document.
|
||||
workbook = new Workbook();
|
||||
workbook.WorkbookArchive = new SaMsZipArchive();
|
||||
if (workbook.WorkbookArchive.OpenArchive(filePath))
|
||||
{
|
||||
ExtractWorkbookElementsFromArchive();
|
||||
}
|
||||
else return SetErrorState("Failed to open document: " + workbook.WorkbookArchive.ErrorStateMessage);
|
||||
}
|
||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
return !HasErrorState();
|
||||
}
|
||||
public bool OpenWorkbook (byte[] workbookData)
|
||||
{
|
||||
CloseWorkbook();
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
using (MemoryStream workbookStream = new MemoryStream(workbookData))
|
||||
{
|
||||
OpenWorkbook(workbookStream);
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
return !HasErrorState();
|
||||
}
|
||||
public bool OpenWorkbook (Stream workbookStream)
|
||||
{
|
||||
CloseWorkbook();
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
// From start of stream.
|
||||
workbookStream.Seek(0, SeekOrigin.Begin);
|
||||
// Open workbook document.
|
||||
workbook = new Workbook();
|
||||
workbook.WorkbookArchive = new SaMsZipArchive();
|
||||
if (workbook.WorkbookArchive.OpenArchive(workbookStream))
|
||||
{
|
||||
ExtractWorkbookElementsFromArchive();
|
||||
}
|
||||
else return SetErrorState("Failed to open document: " + workbook.WorkbookArchive.ErrorStateMessage);
|
||||
}
|
||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
return !HasErrorState();
|
||||
}
|
||||
private bool ExtractWorkbookElementsFromArchive ()
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
// Extract the workbook data.
|
||||
using (MemoryStream workbookFile = workbook.WorkbookArchive.ExtractFileToStream("xl/workbook.xml"))
|
||||
{
|
||||
if (workbookFile == null) return SetErrorState("Failed to load workbook data");
|
||||
workbook.WorkbookDoc = new SaMsXmlDocument();
|
||||
if (workbook.WorkbookDoc.LoadXml(workbookFile))
|
||||
{
|
||||
// Workbook successfully opened.
|
||||
workbook.ActiveSheetPos = 1;
|
||||
// Shared strings:
|
||||
using (MemoryStream sharedStringsFile = workbook.WorkbookArchive.ExtractFileToStream("xl/sharedStrings.xml"))
|
||||
{
|
||||
if (sharedStringsFile != null)
|
||||
{
|
||||
workbook.SharedStringsDoc = new SaMsXmlDocument();
|
||||
workbook.SharedStringsDoc.LoadXml(sharedStringsFile);
|
||||
}
|
||||
}
|
||||
// Styles:
|
||||
using (MemoryStream stylesFile = workbook.WorkbookArchive.ExtractFileToStream("xl/styles.xml"))
|
||||
{
|
||||
if (stylesFile != null)
|
||||
{
|
||||
workbook.StylesDoc = new SaMsXmlDocument();
|
||||
workbook.StylesDoc.LoadXml(stylesFile);
|
||||
}
|
||||
}
|
||||
// Set worksheet count and open first worksheet.
|
||||
PopulateWorksheetCount();
|
||||
OpenWorksheet(1);
|
||||
}
|
||||
else return SetErrorState("Failed to read workbook data");
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
return !HasErrorState();
|
||||
}
|
||||
public override bool SaveDocument (String filePath, int fileFormat, bool bAutomaticallyOverwrite)
|
||||
{
|
||||
ClearErrorState();
|
||||
if (fileFormat == 0)
|
||||
fileFormat = (int)XlFileFormat.xlOpenXMLWorkbook;
|
||||
if (fileFormat != (int)XlFileFormat.xlOpenXMLWorkbook)
|
||||
SetErrorState("Unsupported file format: " + ((XlFileFormat)fileFormat).ToString());
|
||||
if (!HasErrorState() && !workbook.IsValid())
|
||||
SetErrorState("Workbook is not open");
|
||||
SetErrorState("Saving workbook not supported");
|
||||
return !HasErrorState();
|
||||
}
|
||||
public override bool CloseWorkbook ()
|
||||
{
|
||||
ClearErrorState();
|
||||
CloseWorksheet();
|
||||
|
||||
// Clear workbook.
|
||||
if (workbook != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (workbook.StylesDoc != null) workbook.StylesDoc.Dispose(); workbook.StylesDoc = null;
|
||||
if (workbook.SharedStringsDoc != null) workbook.SharedStringsDoc.Dispose(); workbook.SharedStringsDoc = null;
|
||||
if (workbook.WorkbookDoc != null) workbook.WorkbookDoc.Dispose(); workbook.WorkbookDoc = null;
|
||||
if (workbook.WorkbookArchive != null) workbook.WorkbookArchive.Dispose(); workbook.WorkbookArchive = null;
|
||||
}
|
||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
workbook = null;
|
||||
}
|
||||
return !HasErrorState();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// W o r k s h e e t
|
||||
//-------------------------------------------------------------------
|
||||
public override bool IsWorksheetValid ()
|
||||
{
|
||||
return (worksheet != null && worksheet.WorksheetDoc != null);
|
||||
}
|
||||
public override uint WorksheetCount { get { return workbook.WorksheetCount; } }
|
||||
private void PopulateWorksheetCount ()
|
||||
{
|
||||
if (!IsWorkbookValid()) return;
|
||||
try
|
||||
{
|
||||
// Count worksheets in workbook.
|
||||
SaMsXmlElement nodeWorkbook = workbook.WorkbookDoc.GetRootElement();
|
||||
SaMsXmlElement nodeSheets = nodeWorkbook.GetFirstChildElement("sheets");
|
||||
workbook.WorksheetCount = (uint)nodeSheets.GetChildElements("sheet").Count;
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetWorksheetCount", exc); }
|
||||
}
|
||||
public override bool SetWorksheetCount (int worksheetCount)
|
||||
{
|
||||
ClearErrorState();
|
||||
return SetErrorState("Modifying workbook not supported");
|
||||
}
|
||||
public override bool AddWorksheet(String name)
|
||||
{
|
||||
return SetErrorState("Modifying workbook not supported");
|
||||
}
|
||||
public override bool RemoveWorksheet(uint worksheetPos)
|
||||
{
|
||||
return SetErrorState("Modifying workbook not supported");
|
||||
}
|
||||
public override bool OpenWorksheet (uint worksheetPos)
|
||||
{
|
||||
ClearErrorState();
|
||||
if (!workbook.IsValid()) return SetErrorState("Workbook is not open");
|
||||
if (worksheetPos > WorksheetCount) return SetErrorState("Invalid sheet specified");
|
||||
if (worksheetPos <= 0) worksheetPos = Math.Max(1, workbook.ActiveSheetPos);
|
||||
CloseWorksheet();
|
||||
try
|
||||
{
|
||||
worksheet = new Worksheet();
|
||||
// Locate worksheet in workbook by 0-index.
|
||||
SaMsXmlElement workbookElement = workbook.WorkbookDoc.GetRootElement();
|
||||
SaMsXmlElement sheetsElement = workbookElement.GetFirstChildElement("sheets");
|
||||
long sheetCount = 0;
|
||||
foreach (SaMsXmlElement sheetElement in sheetsElement.GetChildElements("sheet"))
|
||||
{
|
||||
sheetCount++;
|
||||
if (sheetCount == worksheetPos)
|
||||
{
|
||||
// Extract the worksheet data.
|
||||
uint sheetId = (uint)StringUtil.ToInt(sheetElement.GetAttributeValue("sheetId"));
|
||||
String worksheetArchivePath = "xl/worksheets/sheet" + worksheetPos.ToString() + ".xml";
|
||||
using (MemoryStream worksheetFile = workbook.WorkbookArchive.ExtractFileToStream(worksheetArchivePath))
|
||||
{
|
||||
if (worksheetFile == null) return SetErrorState("Failed to load worksheet data");
|
||||
worksheet.WorksheetDoc = new SaMsXmlDocument();
|
||||
if (worksheet.WorksheetDoc.LoadXml(worksheetFile))
|
||||
{
|
||||
workbook.ActiveSheetPos = worksheetPos;
|
||||
worksheet.WorksheetPos = worksheetPos;
|
||||
worksheet.WorksheetId = sheetId;
|
||||
worksheet.WorksheetArchivePath = worksheetArchivePath;
|
||||
worksheet.WorksheetName = sheetElement.GetAttributeValue("name");
|
||||
worksheet.ActiveColPos = 1;
|
||||
worksheet.ActiveRowPos = 1;
|
||||
SaMsXmlElement nodeWorksheet = worksheet.WorksheetDoc.GetRootElement();
|
||||
worksheet.Nodes.Cols = nodeWorksheet.GetFirstChildElement("cols");
|
||||
worksheet.Nodes.ActiveCol = worksheet.Nodes.Cols.GetFirstChildElement("col");
|
||||
worksheet.Nodes.Rows = nodeWorksheet.GetFirstChildElement("sheetData");
|
||||
worksheet.Nodes.ActiveRow = worksheet.Nodes.Rows.GetFirstChildElement("row");
|
||||
workbook.ActiveSheetPos = worksheetPos;
|
||||
}
|
||||
else return SetErrorState("Failed to read data for worksheet " + worksheetPos.ToString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (worksheet.WorksheetDoc == null) return SetErrorState("Unable to load worksheet " + worksheetPos.ToString());
|
||||
}
|
||||
catch (Exception exc) { HandleException("OpenWorksheet", exc); }
|
||||
return !HasErrorState();
|
||||
}
|
||||
public override uint WorksheetPos { get { return workbook.ActiveSheetPos; } }
|
||||
public override String WorksheetName
|
||||
{
|
||||
get { return ""; }
|
||||
set { }
|
||||
}
|
||||
public override bool SetWorksheetAttr (SaMsExcelItemAttr attr)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
public override bool CloseWorksheet ()
|
||||
{
|
||||
ClearErrorState();
|
||||
|
||||
if (worksheet != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (worksheet.WorksheetDoc != null) worksheet.WorksheetDoc.Dispose(); worksheet.WorksheetDoc = null;
|
||||
if (worksheet.Nodes.Cols != null) worksheet.Nodes.Cols.Dispose(); worksheet.Nodes.Cols = null;
|
||||
if (worksheet.Nodes.ActiveCol != null) worksheet.Nodes.ActiveCol.Dispose(); worksheet.Nodes.ActiveCol = null;
|
||||
if (worksheet.Nodes.Rows != null) worksheet.Nodes.Rows.Dispose(); worksheet.Nodes.Rows = null;
|
||||
if (worksheet.Nodes.ActiveRow != null) worksheet.Nodes.ActiveRow.Dispose(); worksheet.Nodes.ActiveRow = null;
|
||||
}
|
||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||
worksheet = null;
|
||||
}
|
||||
|
||||
return !HasErrorState();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Worksheet Page Setup.
|
||||
public override bool SetPageSetup (SaMsExcelPageSetup_Config pageSetupConfig)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
public override bool SetPageBreak (uint col, uint row)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C o l u m n s
|
||||
//-------------------------------------------------------------------
|
||||
public override uint GetActiveColPos ()
|
||||
{
|
||||
return worksheet.ActiveColPos;
|
||||
}
|
||||
private SaMsXmlElement GetColElement (uint colPos)
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
if (worksheet.ActiveColPos == colPos) return worksheet.Nodes.ActiveCol;
|
||||
int colCount = 0;
|
||||
foreach (SaMsXmlElement colElement in worksheet.Nodes.Cols.GetChildElements("Col"))
|
||||
{
|
||||
if (++colCount == colPos)
|
||||
{
|
||||
if (worksheet.Nodes.ActiveCol != null) worksheet.Nodes.ActiveCol.Dispose();
|
||||
worksheet.ActiveColPos = colPos;
|
||||
worksheet.Nodes.ActiveCol = colElement;
|
||||
return colElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetColElement", exc); }
|
||||
return new SaMsXmlElement(null);
|
||||
}
|
||||
public override double GetColWidth (uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
// Retrieve width (in points) from column.
|
||||
SaMsXmlNode nodeCol = GetColElement(colPos);
|
||||
double width = nodeCol.GetAttributeValue("width").ToDouble();
|
||||
// Adjust for units.
|
||||
if (unit == SaExcelLogicalUnit.Pixel) return PointsToPixels(width, false);
|
||||
if (unit == SaExcelLogicalUnit.Cm) return PointsToCms(width);
|
||||
if (unit == SaExcelLogicalUnit.Inch) return PointsToInches(width);
|
||||
return width;
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetColWidth", exc); }
|
||||
return 0.0;
|
||||
}
|
||||
public override bool SetColWidth (uint colPos, double fWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// R o w s
|
||||
//-------------------------------------------------------------------
|
||||
public override uint GetActiveRowPos ()
|
||||
{
|
||||
return worksheet.ActiveRowPos;
|
||||
}
|
||||
SaMsXmlElement GetRowElement (uint rowPos)
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
if (worksheet.ActiveRowPos == rowPos) return worksheet.Nodes.ActiveRow;
|
||||
foreach (SaMsXmlElement rowElement in worksheet.Nodes.Rows.GetChildElements("row"))
|
||||
{
|
||||
if (rowElement.GetAttributeValue("r").ToLong() == rowPos)
|
||||
{
|
||||
if (worksheet.Nodes.ActiveRow != null) worksheet.Nodes.ActiveRow.Dispose();
|
||||
worksheet.ActiveRowPos = rowPos;
|
||||
worksheet.Nodes.ActiveRow = rowElement;
|
||||
return rowElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetRowElement", exc); }
|
||||
return new SaMsXmlElement(null);
|
||||
}
|
||||
public override double GetRowHeight (uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
// Retrieve height (in points) from row.
|
||||
SaMsXmlElement rowElement = GetRowElement(rowPos);
|
||||
double height = rowElement.GetAttributeValue("ht").ToDouble();
|
||||
// Adjust for units.
|
||||
if (unit == SaExcelLogicalUnit.Pixel) return PointsToPixels(height, true);
|
||||
if (unit == SaExcelLogicalUnit.Cm) return PointsToCms(height);
|
||||
if (unit == SaExcelLogicalUnit.Inch) return PointsToInches(height);
|
||||
return height;
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetRowHeight", exc); }
|
||||
return 0.0;
|
||||
}
|
||||
public override bool SetRowHeight (uint rowPos, double fHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// R o w s
|
||||
//-------------------------------------------------------------------
|
||||
public override List<DataValue> GetRowDataValues (uint rowPos, int maxColumns = 0)
|
||||
{
|
||||
ClearErrorState();
|
||||
List<DataValue> values = new List<DataValue>();
|
||||
try
|
||||
{
|
||||
SaMsXmlElement rowElement = GetRowElement(rowPos);
|
||||
foreach (SaMsXmlElement cellElement in rowElement.GetChildElements("c"))
|
||||
{
|
||||
// CellId may be needed in case cells are skipped in the data.
|
||||
// Doesn't appear to be the case, even when previous cell is merged with next.
|
||||
String cellId = cellElement.GetAttributeValue("r");
|
||||
values.Add(GetCellDataValue(cellElement));
|
||||
if (maxColumns > 0 && values.Count >= maxColumns) break;
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetRowDataValues", exc); }
|
||||
return values;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C e l l s
|
||||
//-------------------------------------------------------------------
|
||||
SaMsXmlElement GetCellElement (uint colPos, uint rowPos)
|
||||
{
|
||||
ClearErrorState();
|
||||
String cellId = GetCellId(colPos,rowPos);
|
||||
try
|
||||
{
|
||||
SaMsXmlElement rowElement = GetRowElement(rowPos);
|
||||
foreach (SaMsXmlElement cellElement in rowElement.GetChildElements("c"))
|
||||
{
|
||||
if (cellElement.GetAttributeValue("r").EqualsCI(cellId))
|
||||
return cellElement;
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetCellElement", exc); }
|
||||
return new SaMsXmlElement(null);
|
||||
}
|
||||
public override void SetActiveCell (uint colPos, uint rowPos)
|
||||
{
|
||||
// ToDo SetActiveCell.
|
||||
SetErrorState("Not supported");
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
private bool IsCellFormula (uint colPos, uint rowPos)
|
||||
{
|
||||
ClearErrorState();
|
||||
bool bIsFormula = false;
|
||||
try
|
||||
{
|
||||
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
|
||||
bIsFormula = !cellElement.GetAttributeValue("f").IsEmpty();
|
||||
}
|
||||
catch (Exception exc) { HandleException("IsCellFormula", exc); }
|
||||
return bIsFormula;
|
||||
}
|
||||
private bool IsCellNumeric (uint colPos, uint rowPos)
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
|
||||
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
||||
return IsCellNumeric(cellElement, cellStyle);
|
||||
}
|
||||
catch (Exception exc) { HandleException("IsCellNumeric", exc); }
|
||||
return false;
|
||||
}
|
||||
private bool IsCellNumeric (SaMsXmlElement cellElement)
|
||||
{
|
||||
ClearErrorState();
|
||||
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
||||
return IsCellNumeric(cellElement, cellStyle);
|
||||
}
|
||||
private bool IsCellNumeric (SaMsXmlElement cellElement, SaMsExcelStyle cellStyle)
|
||||
{
|
||||
ClearErrorState();
|
||||
return (cellElement.GetAttributeValue("t").IsEmpty() && !IsDateTimeStyle(cellStyle.NumFmtCode));
|
||||
}
|
||||
private bool IsCellDate (uint colPos, uint rowPos)
|
||||
{
|
||||
ClearErrorState();
|
||||
bool bIsDate = false;
|
||||
try
|
||||
{
|
||||
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
|
||||
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
||||
return IsCellDate(cellElement, cellStyle);
|
||||
}
|
||||
catch (Exception exc) { HandleException("IsCellDate", exc); }
|
||||
return bIsDate;
|
||||
}
|
||||
private bool IsCellDate (SaMsXmlElement cellElement)
|
||||
{
|
||||
return IsCellDate(cellElement, GetCellStyle(cellElement));
|
||||
}
|
||||
private bool IsCellDate (SaMsXmlElement cellElement, SaMsExcelStyle cellStyle)
|
||||
{
|
||||
ClearErrorState();
|
||||
return IsDateTimeStyle(cellStyle.NumFmtCode);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
public override String GetCellFormula (uint colPos, uint rowPos)
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
|
||||
String formula = cellElement.GetAttributeValue("f");
|
||||
if (formula.IsEmpty())
|
||||
formula = GetCellText(cellElement, true);
|
||||
return formula;
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetCellFormula", exc); }
|
||||
return "";
|
||||
}
|
||||
private String GetCellText (SaMsXmlElement cellElement, bool trimValue = true)
|
||||
{
|
||||
ClearErrorState();
|
||||
String value = "";
|
||||
try
|
||||
{
|
||||
if (cellElement.GetAttributeValue("t").EqualsCI("s"))
|
||||
value = GetSharedString(cellElement);
|
||||
else
|
||||
value = cellElement.GetChildText("v");
|
||||
if (trimValue) value.TrimAll();
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetCellText", exc); }
|
||||
return value;
|
||||
}
|
||||
public override DataValue GetCellDataValue (uint colPos, uint rowPos)
|
||||
{
|
||||
return GetCellDataValue(GetCellElement(colPos, rowPos), false);
|
||||
}
|
||||
private DataValue GetCellDataValue (SaMsXmlElement cellElement, bool trimTextValue = true)
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
||||
if (cellElement.GetAttributeValue("t").EqualsCI("s"))
|
||||
{
|
||||
String value = GetSharedString(cellElement);
|
||||
if (trimTextValue) value = value.TrimAll();
|
||||
return new DataValue(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
String value = cellElement.GetChildText("v");
|
||||
if (IsDateTimeStyle(cellStyle.NumFmtCode))
|
||||
return new DataValue(DateTime.FromOADate(value.ToDouble()));
|
||||
if (IsCellNumeric(cellElement, cellStyle))
|
||||
{
|
||||
if (value.IsNumeric())
|
||||
return new DataValue(value.ToLong());
|
||||
if (value.IsDecimal())
|
||||
{
|
||||
#if DEBUG
|
||||
//if (StringUtil.ToInt(value) > 600) Debugger.Break();
|
||||
#endif
|
||||
return new DataValue(value.ToDecimal());
|
||||
}
|
||||
}
|
||||
if (trimTextValue) value = value.TrimAll();
|
||||
return new DataValue(value);
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetCellDataValue", exc); }
|
||||
return new DataValue();
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
// Shared string for cell.
|
||||
private String GetSharedString (SaMsXmlElement nodeElement)
|
||||
{
|
||||
ClearErrorState();
|
||||
try
|
||||
{
|
||||
SaMsXmlElement sharedStringElement = GetSharedStringElement(nodeElement);
|
||||
return sharedStringElement.GetChildText("t");
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetSharedString", exc); }
|
||||
return "";
|
||||
}
|
||||
private SaMsXmlElement GetSharedStringElement (SaMsXmlElement cellElement)
|
||||
{
|
||||
ClearErrorState();
|
||||
if (workbook.SharedStringsDoc == null || cellElement == null || !cellElement.Valid) return null;
|
||||
if (!cellElement.GetAttributeValue("t").EqualsCI("s") || !cellElement.GetChildText("v").IsNumeric()) return null;
|
||||
// Shared strings are indexed from 0.
|
||||
long sharedStringIdx = -1;
|
||||
try
|
||||
{
|
||||
long iIdx = cellElement.GetChildText("v").ToLong();
|
||||
SaMsXmlElement sstElement = workbook.SharedStringsDoc.GetRootElement();
|
||||
foreach (SaMsXmlElement siElement in sstElement.GetChildElements("si"))
|
||||
{
|
||||
if (++sharedStringIdx == iIdx)
|
||||
return siElement;
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetSharedStringNode", exc); }
|
||||
return new SaMsXmlElement(null);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
public override bool SetCellFormula (uint colPos, uint rowPos, String value)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
public override bool SetCellFormula (uint colPos, uint rowPos, String value, SaMsExcelItemAttr attr)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
public override bool SetRowFormulas (uint colPosStart, uint rowPos, List<Object> values)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
public override bool SetRangeFormulas (SaMsExcelRange range, List<Object> values)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// C e l l S t y l e
|
||||
//-------------------------------------------------------------------
|
||||
private String GetBuiltInStyleFormat (int numFmtId)
|
||||
{
|
||||
// Ref. http://stackoverflow.com/questions/4730152/what-indicates-an-office-open-xml-cell-contains-a-date-time-value
|
||||
switch (numFmtId)
|
||||
{
|
||||
//
|
||||
case 0: return "General";
|
||||
case 1: return "0";
|
||||
case 2: return "0.00";
|
||||
case 3: return "#,##0";
|
||||
case 4: return "#,##0.00";
|
||||
//
|
||||
case 9: return "0%";
|
||||
case 10: return "0.00%";
|
||||
case 11: return "0.00E+00";
|
||||
case 12: return "# ?/?";
|
||||
case 13: return "# ??/??";
|
||||
case 14: return "mm-dd-yy";
|
||||
case 15: return "d-mmm-yy";
|
||||
case 16: return "d-mmm";
|
||||
case 17: return "mmm-yy";
|
||||
case 18: return "h:mm AM/PM";
|
||||
case 19: return "h:mm:ss AM/PM";
|
||||
case 20: return "h:mm";
|
||||
case 21: return "h:mm:ss";
|
||||
case 22: return "m/d/yy h:mm";
|
||||
//
|
||||
case 37: return "#,##0 ;(#,##0)";
|
||||
case 38: return "#,##0 ;[Red](#,##0)";
|
||||
case 39: return "#,##0.00;(#,##0.00)";
|
||||
case 40: return "#,##0.00;[Red](#,##0.00)";
|
||||
//
|
||||
case 44: return "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)";
|
||||
case 45: return "mm:ss";
|
||||
case 46: return "[h]:mm:ss";
|
||||
case 47: return "mmss.0";
|
||||
case 48: return "##0.0E+0";
|
||||
case 49: return "@";
|
||||
//
|
||||
case 27: return "[$-404]e/m/d";
|
||||
case 30: return "m/d/yy";
|
||||
case 36: return "[$-404]e/m/d";
|
||||
case 50: return "[$-404]e/m/d";
|
||||
case 57: return "[$-404]e/m/d";
|
||||
//
|
||||
case 59: return "t0";
|
||||
case 60: return "t0.00";
|
||||
case 61: return "t#,##0";
|
||||
case 62: return "t#,##0.00";
|
||||
case 67: return "t0%";
|
||||
case 68: return "t0.00%";
|
||||
case 69: return "t# ?/?";
|
||||
case 70: return "t# ??/??";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
private SaMsExcelStyle GetCellStyle (SaMsXmlElement cellElement)
|
||||
{
|
||||
ClearErrorState();
|
||||
SaMsExcelStyle style = new SaMsExcelStyle();
|
||||
if (workbook.SharedStringsDoc == null || cellElement == null || !cellElement.Valid || !cellElement.GetAttributeValue("s").IsNumeric()) return style;
|
||||
// Styles are indexed from 0.
|
||||
long styleIdx = -1;
|
||||
try
|
||||
{
|
||||
long cellStyleIdx = cellElement.GetAttributeValue("s").ToLong();
|
||||
SaMsXmlElement styleSheetElement = workbook.SharedStringsDoc.GetRootElement();
|
||||
SaMsXmlElement cellXfsElement = styleSheetElement.GetFirstChildElement("cellXfs");
|
||||
foreach (SaMsXmlElement xfElement in styleSheetElement.GetChildElements("xf"))
|
||||
{
|
||||
if (++styleIdx == cellStyleIdx)
|
||||
{
|
||||
// Construct style.
|
||||
style.NumFmtId = (int)xfElement.GetAttributeValue("numFmtId").ToLong();
|
||||
style.FontId = (int)xfElement.GetAttributeValue("fontId").ToLong();
|
||||
style.FillId = (int)xfElement.GetAttributeValue("fillId").ToLong();
|
||||
style.BorderId = (int)xfElement.GetAttributeValue("borderId").ToLong();
|
||||
style.XfId = (int)xfElement.GetAttributeValue("xfId").ToLong();
|
||||
style.QuotePrefix = xfElement.GetAttributeValue("quotePrefix").ToBool();
|
||||
style.PivotButton = xfElement.GetAttributeValue("pivotButton").ToBool();
|
||||
style.ApplyNumberFormat = xfElement.GetAttributeValue("applyNumberFormat").ToBool();
|
||||
style.ApplyFont = xfElement.GetAttributeValue("applyFont").ToBool();
|
||||
style.ApplyFill = xfElement.GetAttributeValue("applyFill").ToBool();
|
||||
style.ApplyBorder = xfElement.GetAttributeValue("applyBorder").ToBool();
|
||||
style.ApplyAlignment = xfElement.GetAttributeValue("applyAlignment").ToBool();
|
||||
style.ApplyProtection = xfElement.GetAttributeValue("applyProtection").ToBool();
|
||||
// Alignment.
|
||||
SaMsXmlNode nodeAlignment = xfElement.GetFirstChildElement("alignment");
|
||||
String sAlignHorizontal = nodeAlignment.GetAttributeValue("horizontal");
|
||||
if (sAlignHorizontal.EqualsCI("center")) style.AlignHorizontal = XlHAlign.xlHAlignCenter;
|
||||
else if (sAlignHorizontal.EqualsCI("centerContinuous")) style.AlignHorizontal = XlHAlign.xlHAlignCenterAcrossSelection;
|
||||
else if (sAlignHorizontal.EqualsCI("distributed")) style.AlignHorizontal = XlHAlign.xlHAlignDistributed;
|
||||
else if (sAlignHorizontal.EqualsCI("fill")) style.AlignHorizontal = XlHAlign.xlHAlignFill;
|
||||
else if (sAlignHorizontal.EqualsCI("justify")) style.AlignHorizontal = XlHAlign.xlHAlignJustify;
|
||||
else if (sAlignHorizontal.EqualsCI("left")) style.AlignHorizontal = XlHAlign.xlHAlignLeft;
|
||||
else if (sAlignHorizontal.EqualsCI("right")) style.AlignHorizontal = XlHAlign.xlHAlignRight;
|
||||
String sAlignVertical = nodeAlignment.GetAttributeValue("vertical");
|
||||
if (sAlignVertical.EqualsCI("center")) style.AlignVertical = XlVAlign.xlVAlignCenter;
|
||||
else if (sAlignVertical.EqualsCI("top")) style.AlignVertical = XlVAlign.xlVAlignTop;
|
||||
else if (sAlignVertical.EqualsCI("bottom")) style.AlignVertical = XlVAlign.xlVAlignBottom;
|
||||
else if (sAlignVertical.EqualsCI("distributed")) style.AlignVertical = XlVAlign.xlVAlignDistributed;
|
||||
else if (sAlignVertical.EqualsCI("justify")) style.AlignVertical = XlVAlign.xlVAlignJustify;
|
||||
// Number format.
|
||||
if (style.ApplyNumberFormat)
|
||||
{
|
||||
if (style.NumFmtId >= 164)
|
||||
{
|
||||
SaMsXmlElement numFmtsElement = styleSheetElement.GetFirstChildElement("NumFmts");
|
||||
foreach (SaMsXmlElement numFmtElement in numFmtsElement.GetChildElements("numFmt"))
|
||||
{
|
||||
if (numFmtElement.GetAttributeValue("numFmtId").ToLong() == style.NumFmtId)
|
||||
{
|
||||
style.NumFmtCode = numFmtElement.GetAttributeValue("formatCode");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else style.NumFmtCode = GetBuiltInStyleFormat(style.NumFmtId);
|
||||
}
|
||||
// Font.
|
||||
if (style.ApplyFont)
|
||||
{
|
||||
}
|
||||
// Fill.
|
||||
if (style.ApplyFill)
|
||||
{
|
||||
}
|
||||
// Borders.
|
||||
if (style.ApplyBorder)
|
||||
{
|
||||
}
|
||||
// Alignment.
|
||||
if (style.ApplyAlignment)
|
||||
{
|
||||
}
|
||||
// Protection.
|
||||
if (style.ApplyProtection)
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exc) { HandleException("GetStyleNode", exc); }
|
||||
return style;
|
||||
}
|
||||
private bool IsDateStyle (String numFormat)
|
||||
{
|
||||
// Ref. http://stackoverflow.com/questions/19034805/how-to-distinguish-inline-numbers-from-ole-automation-date-numbers-in-openxml-sp/19582685#19582685
|
||||
if (IsTimeStyle(numFormat)) return false;
|
||||
if (numFormat.Contains("d")) return true;
|
||||
if (numFormat.Contains("m")) return true;
|
||||
if (numFormat.Contains("y")) return true;
|
||||
return false;
|
||||
}
|
||||
private bool IsTimeStyle (String numFormat)
|
||||
{
|
||||
if (numFormat.Contains("h")) return true;
|
||||
if (numFormat.Contains(":mm")) return true;
|
||||
if (numFormat.Contains("mm:")) return true;
|
||||
if (numFormat.Contains(":ss")) return true;
|
||||
return false;
|
||||
}
|
||||
private bool IsDateTimeStyle (String numFormat)
|
||||
{
|
||||
return (IsDateStyle(numFormat) || IsTimeStyle(numFormat));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Cell attributes.
|
||||
public override bool SetRangeAttr (SaMsExcelRange range, SaMsExcelItemAttr attr)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Add image to sheet.
|
||||
public override bool InsertImage (SaMsExcelImage_Config imageConfig)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public override bool FreezePanes (uint colPos, uint rowPos)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public override bool AutoFit (SaMsExcelRange range)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public override bool SelectRange (SaMsExcelRange range)
|
||||
{
|
||||
return SetErrorState("Not supported");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using Sarand.Net.Standard.Base.Procs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace Sarand.Net.Standard.Proc.Procs
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaProcess : SaProcess_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Definitions.
|
||||
public new class Config : SaProcess_Base.Config
|
||||
{
|
||||
protected Config() : base()
|
||||
{ }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private Config config;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaProcess(Config config) :
|
||||
base(config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Utilities.
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Run asynchronous.
|
||||
//-------------------------------------------------------------------
|
||||
public bool RunAsync()
|
||||
{
|
||||
// Run on separate thread.
|
||||
Thread thread = new Thread(new ThreadStart(RunOnThread));
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
return true;
|
||||
}
|
||||
private void RunOnThread()
|
||||
{
|
||||
RunProcess();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@ using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Xml
|
||||
namespace Sarand.Net.Standard.Proc.Xml
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaMsXmlDocument : SaErrorStateItem
|
||||
+1
-1
@@ -8,7 +8,7 @@ using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Xml
|
||||
namespace Sarand.Net.Standard.Proc.Xml
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaMsXmlElement : SaMsXmlNode
|
||||
@@ -8,7 +8,7 @@ using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Xml
|
||||
namespace Sarand.Net.Standard.Proc.Xml
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaMsXmlNode : SaErrorStateItem
|
||||
@@ -8,7 +8,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Xml
|
||||
namespace Sarand.Net.Standard.Proc.Xml
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaXmlNamespace
|
||||
+1
-1
@@ -9,7 +9,7 @@ using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Data.Zip
|
||||
namespace Sarand.Net.Standard.Proc.Zip
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaMsZipArchive : SaErrorStateItem
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Data\Word\" />
|
||||
<Folder Include="Proc\Word\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
Reference in New Issue
Block a user