Saxonite 1.2.11.2
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
# Sarand
|
# Sarand
|
||||||
|
|
||||||
## Common Projects Visual Studio 2019
|
## Common Projects Visual Studio 2022
|
||||||
|
|
||||||
### Modules
|
### Modules
|
||||||
|
|
||||||
|
* NB All projects upgraded to .Net 6, 28Nov23.
|
||||||
* SACS Standard Base
|
* SACS Standard Base
|
||||||
* Base class library. .Net Standard 2.1. C#.
|
* Base class library. .Net Standard 2.1. C#.
|
||||||
* SACS Standard Dbas
|
* SACS Standard Dbas
|
||||||
@@ -13,7 +14,7 @@
|
|||||||
* SACS Standard Mob
|
* SACS Standard Mob
|
||||||
* Base Mobile application library. .Net Standard 2.1. C#.
|
* Base Mobile application library. .Net Standard 2.1. C#.
|
||||||
* SACS Core Web
|
* SACS Core Web
|
||||||
* Base Web application library. .Net Core 3.1. C#.
|
* Base Web application library. [C# .Net 6]
|
||||||
* SACS Core Unit Tests
|
* SACS Core Unit Tests
|
||||||
* Unit Tests. .Net Core 3.1. C#.
|
* Unit Tests. [C# .Net 6]
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 16.0.31112.23
|
VisualStudioVersion = 17.8.34316.72
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SacsStandardBase", "SacsStandardBase\SacsStandardBase.csproj", "{3A8EE4B3-2335-420B-9619-D1622AF511FA}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SacsStandardBase", "SacsStandardBase\SacsStandardBase.csproj", "{3A8EE4B3-2335-420B-9619-D1622AF511FA}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -20,6 +20,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution files", "Solution
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SacsStandardAccounts", "SacsStandardAccounts\SacsStandardAccounts.csproj", "{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SacsStandardAccounts", "SacsStandardAccounts\SacsStandardAccounts.csproj", "{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SacsStandardProc", "SacsStandardProc\SacsStandardProc.csproj", "{3988EE9F-FFCD-481A-AF5E-AA7E5DB5A415}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -50,6 +52,10 @@ Global
|
|||||||
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.Build.0 = Release|Any CPU
|
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3988EE9F-FFCD-481A-AF5E-AA7E5DB5A415}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3988EE9F-FFCD-481A-AF5E-AA7E5DB5A415}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3988EE9F-FFCD-481A-AF5E-AA7E5DB5A415}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3988EE9F-FFCD-481A-AF5E-AA7E5DB5A415}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Sacs.UnitTests.Net.Standard.Base.Utils
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class SerializableUtil_Tester
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Definitions.
|
||||||
|
[Serializable]
|
||||||
|
private class TestData
|
||||||
|
{
|
||||||
|
public String stringValue = "String Value";
|
||||||
|
public long longValue = 123456;
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
private class TestDataA : TestData
|
||||||
|
{
|
||||||
|
public TestDataA()
|
||||||
|
{
|
||||||
|
stringValue = "String Value A";
|
||||||
|
longValue = 654321;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Data members.
|
||||||
|
private Random random = new Random();
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Deep Copy.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void SerializableUtil_DeepCopy()
|
||||||
|
{
|
||||||
|
// Clone test data.
|
||||||
|
TestData data = new TestData();
|
||||||
|
TestData data_DeepCopy = SerializableUtil.DeepCopy(data);
|
||||||
|
|
||||||
|
// Verify results.
|
||||||
|
Assert.AreEqual(true, data_DeepCopy is TestData);
|
||||||
|
Assert.AreEqual(data.stringValue, data_DeepCopy.stringValue);
|
||||||
|
Assert.AreEqual(data.longValue, data_DeepCopy.longValue);
|
||||||
|
|
||||||
|
// Clone test data A.
|
||||||
|
TestDataA dataA = new TestDataA();
|
||||||
|
TestDataA dataA_DeepCopy = SerializableUtil.DeepCopy(dataA);
|
||||||
|
|
||||||
|
// Verify results.
|
||||||
|
Assert.AreEqual(true, dataA_DeepCopy is TestData);
|
||||||
|
Assert.AreEqual(true, dataA_DeepCopy is TestDataA);
|
||||||
|
Assert.AreEqual(dataA.stringValue, dataA_DeepCopy.stringValue);
|
||||||
|
Assert.AreEqual(dataA.longValue, dataA_DeepCopy.longValue);
|
||||||
|
Assert.AreNotEqual(data.stringValue, dataA_DeepCopy.stringValue);
|
||||||
|
Assert.AreNotEqual(data.longValue, dataA_DeepCopy.longValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
|
||||||
|
namespace Sarand.UnitTests.Core.Base.Utils
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class SysUtil_Tester
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Data members.
|
||||||
|
private static readonly String ClassName_GeneratedMemberName_Prefix = "<";
|
||||||
|
private static readonly String ClassName_CompilerGeneratedClass = ClassName_GeneratedMemberName_Prefix + ">c";
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Calling code class name.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void SysUtil_GetCallerClassName_Test()
|
||||||
|
{
|
||||||
|
// Leading spaces.
|
||||||
|
Assert.AreNotEqual(null, SysUtil.GetCallerClassName());
|
||||||
|
Assert.AreNotEqual("", SysUtil.GetCallerClassName());
|
||||||
|
Assert.AreEqual("SysUtil_Tester", SysUtil.GetCallerClassName());
|
||||||
|
|
||||||
|
// Compiler generated context.
|
||||||
|
Func<string> temp = () => { return SysUtil.GetCallerClassName(); };
|
||||||
|
Assert.AreEqual(ClassName_CompilerGeneratedClass, temp());
|
||||||
|
|
||||||
|
// Anonymous function.
|
||||||
|
Assert.AreEqual(ClassName_CompilerGeneratedClass, ((Func<string>)(() => SysUtil.GetCallerClassName()))());
|
||||||
|
Assert.AreEqual(ClassName_CompilerGeneratedClass, new Func<string>(() => SysUtil.GetCallerClassName())());
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Calling code function name.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void SysUtil_GetCallerMemberName_Test()
|
||||||
|
{
|
||||||
|
// Leading spaces.
|
||||||
|
Assert.AreNotEqual(null, SysUtil.GetCallerMemberName());
|
||||||
|
Assert.AreNotEqual("", SysUtil.GetCallerMemberName());
|
||||||
|
Assert.AreEqual("SysUtil_GetCallerMemberName_Test", SysUtil.GetCallerMemberName());
|
||||||
|
Assert.AreEqual(nameof(SysUtil_GetCallerMemberName_Test), SysUtil.GetCallerMemberName());
|
||||||
|
Assert.AreEqual(MethodBase.GetCurrentMethod().Name, SysUtil.GetCallerMemberName());
|
||||||
|
|
||||||
|
// Compiler generated context.
|
||||||
|
Func<string> temp = () => { return SysUtil.GetCallerMemberName(); };
|
||||||
|
Assert.AreEqual(MethodBase.GetCurrentMethod().Name, temp());
|
||||||
|
|
||||||
|
// Anonymous function.
|
||||||
|
Assert.AreEqual(MethodBase.GetCurrentMethod().Name, ((Func<string>)(() => SysUtil.GetCallerMemberName()))());
|
||||||
|
Assert.AreEqual(MethodBase.GetCurrentMethod().Name, new Func<string>(() => SysUtil.GetCallerMemberName())());
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Calling code file path.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void SysUtil_GetCallerFilePath_Test()
|
||||||
|
{
|
||||||
|
// Leading spaces.
|
||||||
|
Assert.AreNotEqual(null, SysUtil.GetCallerFilePath());
|
||||||
|
Assert.AreNotEqual("", SysUtil.GetCallerFilePath());
|
||||||
|
Assert.AreEqual(@"D:\Sarand\Projects\Users\AHoward\VS2022\Common-VS\Workspace\SacsCoreUnitTests\Standard\Base\Utils\SysUtil_Tester.cs", SysUtil.GetCallerFilePath());
|
||||||
|
Assert.AreEqual(true, SysUtil.GetCallerFilePath().EndsWith("SysUtil_Tester.cs"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Calling code line number.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void SysUtil_GetCallerLineNumber_Test()
|
||||||
|
{
|
||||||
|
// Leading spaces.
|
||||||
|
Assert.AreNotEqual(0, SysUtil.GetCallerLineNumber());
|
||||||
|
Assert.AreEqual((new StackFrame(0, true)).GetFileLineNumber(), SysUtil.GetCallerLineNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Calling code file path.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void SysUtil_GetCallerClassMethod_Test()
|
||||||
|
{
|
||||||
|
// Leading spaces.
|
||||||
|
Assert.AreNotEqual(null, SysUtil.GetCallerClassMethod());
|
||||||
|
Assert.AreNotEqual("", SysUtil.GetCallerClassMethod());
|
||||||
|
Assert.AreEqual(GetType().Name + "." + MethodBase.GetCurrentMethod().Name, SysUtil.GetCallerClassMethod());
|
||||||
|
Assert.AreEqual(nameof(SysUtil_Tester) + "." + nameof(SysUtil_GetCallerClassMethod_Test), SysUtil.GetCallerClassMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Calling code file path.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
[TestMethod]
|
||||||
|
public void SysUtil_Fn_Test()
|
||||||
|
{
|
||||||
|
// Leading spaces.
|
||||||
|
Assert.AreNotEqual(null, SysUtil.Fn);
|
||||||
|
Assert.AreNotEqual("", SysUtil.Fn);
|
||||||
|
Assert.AreEqual(GetType().Name + "." + MethodBase.GetCurrentMethod().Name, SysUtil.Fn);
|
||||||
|
Assert.AreEqual(nameof(SysUtil_Tester) + "." + nameof(SysUtil_Fn_Test), SysUtil.Fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>Sacs.Net.Core</RootNamespace>
|
<RootNamespace>Sacs</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
|
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,423 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Localization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Sarand.Net.Standard.Base.App;
|
||||||
|
using Sarand.Net.Standard.Base.Core;
|
||||||
|
using Sarand.Net.Standard.Base.Helpers;
|
||||||
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Sacs.Web.Components
|
||||||
|
{
|
||||||
|
//=======================================================================
|
||||||
|
public class SaController : Controller
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Protected construction - use derived objects.
|
||||||
|
/// </summary>
|
||||||
|
protected SaController()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Properties.
|
||||||
|
private static String ClassName { get; } = nameof(SaController);
|
||||||
|
public DateTime CreatedAt { get; } = DateTime.Now;
|
||||||
|
public bool DebugMode { get; } = SacsSystem.DebugMode;
|
||||||
|
/// <summary>
|
||||||
|
/// Indicate whether session data should be stored by action.
|
||||||
|
/// <para>Any action that might modify the session data must store it.</para>
|
||||||
|
/// <para>Some actions such as scoring a password's complexity don't need to.</para>
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool StoreSessionData { get; protected set; } = true;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Culture.
|
||||||
|
private CultureInfo sessionCulture;
|
||||||
|
private CultureInfo RequestCulture { get { return Request.HttpContext.Features.Get<IRequestCultureFeature>().RequestCulture.Culture ?? CultureInfo.InvariantCulture; } }
|
||||||
|
public CultureInfo SessionCulture
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (sessionCulture == null)
|
||||||
|
{
|
||||||
|
sessionCulture = RequestCulture;
|
||||||
|
// ToDo Adjust culture if needed.
|
||||||
|
}
|
||||||
|
return sessionCulture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private string LanguageIso2
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var feature = HttpContext.Features.Get<IRequestCultureFeature>();
|
||||||
|
return feature.RequestCulture.UICulture.TwoLetterISOLanguageName.ToLower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Redirection locations.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public static readonly String ParamName_SessionExpired = "SessionExpired";
|
||||||
|
public enum RedirectLocation
|
||||||
|
{
|
||||||
|
WebAppBase,
|
||||||
|
WebAppHome,
|
||||||
|
WebAppHome_SessionExpired,
|
||||||
|
}
|
||||||
|
public String GetRedirectLocation(RedirectLocation redirectLocation)
|
||||||
|
{
|
||||||
|
string protocol = Request.Scheme;
|
||||||
|
var parameters = new RouteValueDictionary();
|
||||||
|
String homeAction = Url.Action("Index", "Home", parameters, protocol);
|
||||||
|
switch (redirectLocation)
|
||||||
|
{
|
||||||
|
case RedirectLocation.WebAppBase:
|
||||||
|
return Regex.Replace(homeAction, "\\/$", "") + "/";
|
||||||
|
case RedirectLocation.WebAppHome:
|
||||||
|
return homeAction;
|
||||||
|
case RedirectLocation.WebAppHome_SessionExpired:
|
||||||
|
// Set the session expired parameter so that the page can report it.
|
||||||
|
// NB Paramater must have a value to be included in the URL query string.
|
||||||
|
parameters.Add(ParamName_SessionExpired, "1");
|
||||||
|
return homeAction;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Action execution events.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override void OnActionExecuting(ActionExecutingContext filterContext)
|
||||||
|
{
|
||||||
|
//if (DebugMode) SaLogger.Debug(GetType().Name + ".OnActionExecuting" + (ViewData.Model != null ? " Model: " + ViewData.Model : ""));
|
||||||
|
|
||||||
|
base.OnActionExecuting(filterContext);
|
||||||
|
}
|
||||||
|
public override void OnActionExecuted(ActionExecutedContext filterContext)
|
||||||
|
{
|
||||||
|
//if (DebugMode) SaLogger.Debug(GetType().Name + ".OnActionExecuted" + (ViewData.Model != null ? " Model: " + ViewData.Model : ""));
|
||||||
|
|
||||||
|
base.OnActionExecuted(filterContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public static String EncryptParameters(NameValueCollection parameters, String base64IV, String base64Key)
|
||||||
|
{
|
||||||
|
String fn = ClassName + ".EncryptParameters";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Copy the list of parameters and sort the keys.
|
||||||
|
NameValueCollection parametersToEncrypt = new NameValueCollection(parameters);
|
||||||
|
String[] paramKeys = parametersToEncrypt.AllKeys;
|
||||||
|
Array.Sort(paramKeys);
|
||||||
|
|
||||||
|
// Serialise parameters as if in a URL query string - so that they can be deserialised in DecryptParameters() below.
|
||||||
|
// Start with a random length parameter name at start of list to obscure the encryption.
|
||||||
|
string queryString = SacsRandomHelper.getRandomLengthNumber(4) + "&";
|
||||||
|
queryString += String.Join("&", paramKeys.Select(a => a + "=" + HttpUtility.UrlEncode(parametersToEncrypt[a])));
|
||||||
|
|
||||||
|
// Encrypt data.
|
||||||
|
String encrypted = SacsEncryptionHelper.Encrypt(queryString, base64IV, base64Key);
|
||||||
|
//if (SacsSystem.DebugMode) SaLogger.Debug(fn + "\n\tData: " + queryString + " \n\tEncrypted: " + encrypted);
|
||||||
|
return encrypted;
|
||||||
|
}
|
||||||
|
catch (Exception exc) { SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
public static NameValueCollection DecryptParameters(String encrypted, String base64IV, String base64Key)
|
||||||
|
{
|
||||||
|
String fn = ClassName + ".DecryptParameters";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String queryString = SacsEncryptionHelper.Decrypt(encrypted, base64IV, base64Key);
|
||||||
|
//if (SacsSystem.DebugMode) SaLogger.Debug(fn + " \n\tEncrypted: " + encrypted + "\n\tData: " + queryString);
|
||||||
|
return HttpUtility.ParseQueryString(queryString);
|
||||||
|
}
|
||||||
|
catch (Exception exc) { SaLogger.Warn(fn + " " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||||
|
return new NameValueCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Cookies.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>Retrieve the value from the named request cookie.</summary>
|
||||||
|
public String GetRequestCookie(String key)
|
||||||
|
{
|
||||||
|
if (Request.Cookies.ContainsKey(key))
|
||||||
|
return Request.Cookies[key];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/// <summary>Set the value against the named response cookie.</summary>
|
||||||
|
public void SetResponseCookie(string key, string value, DateTime? expiresAt = null, bool isEssential = false)
|
||||||
|
{
|
||||||
|
CookieOptions options = new CookieOptions();
|
||||||
|
options.HttpOnly = true;
|
||||||
|
options.Secure = true;
|
||||||
|
options.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
|
||||||
|
if (expiresAt.HasValue)
|
||||||
|
options.Expires = expiresAt;
|
||||||
|
if (isEssential)
|
||||||
|
options.IsEssential = true;
|
||||||
|
Response.Cookies.Append(key, value, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Ajax actions.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
protected static readonly Encoding ajaxResponseEncoding = Encoding.UTF8;
|
||||||
|
protected IActionResult GetAjaxResult_GoHome(AjaxResponse_Base responseData)
|
||||||
|
{
|
||||||
|
responseData.SetGoHome();
|
||||||
|
return Json(responseData);
|
||||||
|
}
|
||||||
|
protected IActionResult GetAjaxResult_InvalidSession(AjaxResponse_Base responseData)
|
||||||
|
{
|
||||||
|
responseData.SetGoHome();
|
||||||
|
return Json(responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Response data.
|
||||||
|
// Null values are ignored by JSON serialisation.
|
||||||
|
// - See Saxonite.Net.Core.Web.Base.App.SaxStartup.ConfigureServices()
|
||||||
|
// - Ref. config.services.AddMvc(...).AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = true; });
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Base response data - for simple responses.
|
||||||
|
public class AjaxResponse_Base
|
||||||
|
{
|
||||||
|
// Response status.
|
||||||
|
public bool? Success { get; set; } = null;
|
||||||
|
public bool? Error { get; set; } = null;
|
||||||
|
public bool? SessionExpired { get; protected set; } = null;
|
||||||
|
public bool? GoHome { get; protected set; } = null;
|
||||||
|
public AjaxResponse_Base SetSessionExpired(String title, String text)
|
||||||
|
{
|
||||||
|
SessionExpired = true;
|
||||||
|
return SetMessage(title, text);
|
||||||
|
}
|
||||||
|
public AjaxResponse_Base SetGoHome()
|
||||||
|
{
|
||||||
|
GoHome = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public AjaxResponse_Base SetGoHome(String title, String text)
|
||||||
|
{
|
||||||
|
GoHome = true;
|
||||||
|
return SetMessage(title, text);
|
||||||
|
}
|
||||||
|
// Message - displays alert popup.
|
||||||
|
public class MessageData
|
||||||
|
{
|
||||||
|
public String Title { get; set; }
|
||||||
|
public String Text { get; set; }
|
||||||
|
}
|
||||||
|
public MessageData Message { get; private set; }
|
||||||
|
public AjaxResponse_Base SetMessage(String title, String text)
|
||||||
|
{
|
||||||
|
if (!StringUtil.IsEmpty(text))
|
||||||
|
Message = new MessageData() { Title = title, Text = text };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public class AjaxResponse_Data : AjaxResponse_Base
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Construction.
|
||||||
|
protected AjaxResponse_Data(SaModel model)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
/// <summary>Item data - Common properties for data items.</summary>
|
||||||
|
public class ItemData_Base
|
||||||
|
{
|
||||||
|
// Common item properties.
|
||||||
|
public String Id { get; set; }
|
||||||
|
public String Notes { get; set; }
|
||||||
|
public String StatusCode { get; set; }
|
||||||
|
public String StatusDesc { get; set; }
|
||||||
|
// Flags for common status values.
|
||||||
|
// Return true or null so that property is not serialised when false.
|
||||||
|
public bool? Awaiting { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Awaiting)) ? true : (bool?)null; } }
|
||||||
|
public bool? Active { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Active)) ? true : (bool?)null; } }
|
||||||
|
public bool? Inactive { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Inactive)) ? true : (bool?)null; } }
|
||||||
|
public bool? Deleted { get { return StatusCode.EqualsCI(SacsSystem.GetStatusCode(SaStatus.Deleted)) ? true : (bool?)null; } }
|
||||||
|
/// <summary>Created on date - YYYYMMDD</summary>
|
||||||
|
public String CreatedOn { get; set; }
|
||||||
|
/// <summary>Created on date - formatted per locale</summary>
|
||||||
|
public String CreatedOnFmt { get; set; }
|
||||||
|
/// <summary>Updated on date - YYYYMMDD</summary>
|
||||||
|
public String UpdatedOn { get; set; }
|
||||||
|
/// <summary>Updated on date - formatted per locale</summary>
|
||||||
|
public String UpdatedOnFmt { get; set; }
|
||||||
|
}
|
||||||
|
/// <summary>Contact Method properties.</summary>
|
||||||
|
public class ContactMethodData
|
||||||
|
{
|
||||||
|
public String Method { get; set; }
|
||||||
|
public String MethodCaption { get; set; }
|
||||||
|
public String Value { get; set; }
|
||||||
|
}
|
||||||
|
/// <summary>Address properties.</summary>
|
||||||
|
public class AddressData : ItemData_Base
|
||||||
|
{
|
||||||
|
public String Line1 { get; set; }
|
||||||
|
public String Line2 { get; set; }
|
||||||
|
public String Line3 { get; set; }
|
||||||
|
public String Town { get; set; }
|
||||||
|
public String RegionIdProvince { get; set; }
|
||||||
|
public String RegionNameProvince { get; set; }
|
||||||
|
public String RegionIdCountry { get; set; }
|
||||||
|
public String RegionNameCountry { get; set; }
|
||||||
|
public String PostalCode { get; set; }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Item data with label and value.
|
||||||
|
/// </summary>
|
||||||
|
public class ItemLabelValue
|
||||||
|
{
|
||||||
|
public String Label { get; set; }
|
||||||
|
public String Value { get; set; }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Item data with just Id and name.
|
||||||
|
/// <para>- Id is String to allow for obfuscated values.</para>
|
||||||
|
/// </summary>
|
||||||
|
public class ItemIdName
|
||||||
|
{
|
||||||
|
public String Id { get; set; }
|
||||||
|
public String Name { get; set; }
|
||||||
|
}
|
||||||
|
/// <summary>Item code and desc values.</summary>
|
||||||
|
public class ItemCodeDesc
|
||||||
|
{
|
||||||
|
public String Code { get; set; }
|
||||||
|
public String Desc { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Form data.
|
||||||
|
public class FormControlValue
|
||||||
|
{
|
||||||
|
public FormControlValue(String controlName, String value, String error)
|
||||||
|
{
|
||||||
|
ControlName = controlName;
|
||||||
|
Value = value;
|
||||||
|
Error = error;
|
||||||
|
}
|
||||||
|
public String ControlName { get; }
|
||||||
|
public String Value { get; set; }
|
||||||
|
public String Error { get; set; }
|
||||||
|
}
|
||||||
|
private readonly Dictionary<String, FormControlValue> controlValues = new Dictionary<String, FormControlValue>();
|
||||||
|
public List<FormControlValue> ControlValues { get { return controlValues.Count > 0 ? controlValues.Values.ToList() : null; } }
|
||||||
|
public void SetControlValue(String controlName, String value, String error = null)
|
||||||
|
{
|
||||||
|
if (controlValues.ContainsKey(controlName))
|
||||||
|
{
|
||||||
|
// Modify existing entry in the list.
|
||||||
|
FormControlValue controlValue = controlValues[controlName];
|
||||||
|
if (value != null) controlValue.Value = value;
|
||||||
|
if (error != null) controlValue.Error = error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Add new control to list.
|
||||||
|
controlValues.Add(controlName, new FormControlValue(controlName, value, error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>Assign the error to the control by name and return this response data.</summary>
|
||||||
|
public AjaxResponse_Data SetControlError(String controlName, String error)
|
||||||
|
{
|
||||||
|
return SetControlError(controlName, error, this);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Assign the error to the control by name and return the specified value.
|
||||||
|
/// <para>- Allows alternative return values to be specified (eg. 'false') to avoid separate return statement in calling routine.</para>
|
||||||
|
/// </summary>
|
||||||
|
public T SetControlError<T>(String controlName, String error, T returnValue)
|
||||||
|
{
|
||||||
|
SetControlValue(controlName, null, error);
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
public bool HasControlErrors()
|
||||||
|
{
|
||||||
|
foreach (FormControlValue controlValue in controlValues.Values)
|
||||||
|
{
|
||||||
|
if (!StringUtil.IsEmpty(controlValue.Error)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Notification - briefly displays after response received.
|
||||||
|
public class NotificationData
|
||||||
|
{
|
||||||
|
public String Title { get; set; }
|
||||||
|
public String Message { get; set; }
|
||||||
|
}
|
||||||
|
public NotificationData Notification { get; private set; }
|
||||||
|
public AjaxResponse_Data SetNotification(String title, String message)
|
||||||
|
{
|
||||||
|
Notification = new NotificationData() { Title = title, Message = message };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Paged data.
|
||||||
|
public class PagingData
|
||||||
|
{
|
||||||
|
public PagingData(SaModel model) :
|
||||||
|
this(model.Paging.PageNo, model.Paging.PageLength, model.Paging.ItemCount, model.Paging.ItemTotal)
|
||||||
|
{ }
|
||||||
|
public PagingData(uint pageNo, ushort pageLength, ushort itemCount, ulong itemTotal)
|
||||||
|
{
|
||||||
|
PageNo = pageNo;
|
||||||
|
PageLength = pageLength;
|
||||||
|
ItemCount = itemCount;
|
||||||
|
ItemTotal = itemTotal;
|
||||||
|
}
|
||||||
|
public bool Paged { get { return (PageNo > 0 && PageLength > 0 && ItemTotal > PageLength); } }
|
||||||
|
public uint PageNo { get; } = 0;
|
||||||
|
public ushort PageLength { get; } = 0;
|
||||||
|
public uint PageCount { get { return (PageLength > 0 ? (uint)Math.Ceiling((decimal)ItemTotal / PageLength) : 0); } }
|
||||||
|
public ushort ItemCount { get; } = 0;
|
||||||
|
public ulong ItemTotal { get; } = 0;
|
||||||
|
}
|
||||||
|
public PagingData Paging { get; private set; }
|
||||||
|
public void SetPaging(SaModel model)
|
||||||
|
{
|
||||||
|
Paging = new PagingData(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
//=======================================================================
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
using Sarand.Net.Standard.Base.App;
|
||||||
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static Sarand.Net.Standard.Base.Bus.SaErrorStateItem;
|
||||||
|
|
||||||
|
namespace Sacs.Web.Components
|
||||||
|
{
|
||||||
|
//=======================================================================
|
||||||
|
public class SaModel
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Data members.
|
||||||
|
private readonly List<String> infoMessages = new List<string>();
|
||||||
|
private readonly List<String> warningMessages = new List<string>();
|
||||||
|
private readonly List<String> errorMessages = new List<string>();
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Protected construction - use derived objects.
|
||||||
|
/// </summary>
|
||||||
|
protected SaModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Properties.
|
||||||
|
public bool DebugMode { get; } = SacsSystem.DebugMode;
|
||||||
|
public bool OK { get { return !HasMessages(); } }
|
||||||
|
public virtual bool ProhibitCache { get; set; } = true;
|
||||||
|
public String PageCaption { get; set; }
|
||||||
|
public bool IncludeGoogleAnalytics { get; set; } = false;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Page configuration.
|
||||||
|
// Views can be registered to avoid multiple inclusions in a page.
|
||||||
|
private HashSet<String> registeredViews = new HashSet<String>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
/// <summary>
|
||||||
|
/// Views can be registered to avoid multiple inclusions in a page.
|
||||||
|
/// <para>Only generate view content if this method returns true.</para>
|
||||||
|
/// </summary>
|
||||||
|
public bool RegisterView(String viewName)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (registeredViews.Contains(viewName))
|
||||||
|
SaLogger.Warn(this.GetType().Name + ".RegisterView View already registered: " + viewName);
|
||||||
|
#endif
|
||||||
|
return registeredViews.Add(viewName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Version parameter for includes.
|
||||||
|
public String HrefVersion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
DateTime versionDate = SacsSystem.AssemblyBuildAt;
|
||||||
|
if (!DateUtil.IsValid(versionDate) || SacsSystem.DebugMode)
|
||||||
|
versionDate = DateTime.Now;
|
||||||
|
return DateUtil.Format(versionDate, "yyyyMMdd" /*+ (SacsSystem.Debug ? "HHmm" : "")*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Additional includes.
|
||||||
|
public HashSet<String> AdditionalFiles_CSS { get; set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
public HashSet<String> AdditionalFiles_JS { get; set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Redirection locations.
|
||||||
|
public class RedirectLocationData
|
||||||
|
{
|
||||||
|
// Properties populated in Controller_Base.OnActionExecuted.
|
||||||
|
public String Base { get; set; }
|
||||||
|
public String Home { get; set; }
|
||||||
|
public String Home_SessionExpired { get; set; }
|
||||||
|
}
|
||||||
|
public RedirectLocationData RedirectLocation { get; } = new RedirectLocationData();
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Paging properties.
|
||||||
|
public class DataPaging
|
||||||
|
{
|
||||||
|
private DbQuery.Paging paging { get; } = new DbQuery.Paging();
|
||||||
|
public void PopulatePagingTo(DbQuery.Paging resultsPaging)
|
||||||
|
{
|
||||||
|
resultsPaging.PageLength = paging.PageLength;
|
||||||
|
resultsPaging.PageNo = paging.PageNo;
|
||||||
|
}
|
||||||
|
public bool IsPaged { get { return paging.Paged; } }
|
||||||
|
public uint PageNo { get { return paging.PageNo; } set { paging.PageNo = value; } }
|
||||||
|
public String PageNoValue { get { return paging.PageNo.ToString(); } set { paging.PageNo = (uint)StringUtil.ToInt(value); } }
|
||||||
|
public ushort PageLength { get { return paging.PageLength; } set { paging.PageLength = value; } }
|
||||||
|
public String PageLengthValue { get { return paging.PageLength.ToString(); } set { paging.PageLength = (ushort)StringUtil.ToShort(value); } }
|
||||||
|
public uint PageCount { get { return (PageLength > 0 ? (uint)Math.Ceiling((decimal)ItemTotal / paging.PageLength) : 0); } }
|
||||||
|
public ushort ItemCount { get; set; }
|
||||||
|
private ulong itemTotal = 0;
|
||||||
|
public ulong ItemTotal
|
||||||
|
{
|
||||||
|
get { return itemTotal; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
itemTotal = value;
|
||||||
|
// Check whether the total number of items is less than the current page and reduce page no if needed.
|
||||||
|
if (IsPaged && (PageNo - 1) * PageLength > itemTotal)
|
||||||
|
PageNo = (uint)((itemTotal - 1) / PageLength + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public DataPaging Paging { get; } = new DataPaging();
|
||||||
|
public void PopulatePagingTo(DbQuery.Paging resultsPaging)
|
||||||
|
{
|
||||||
|
Paging.PopulatePagingTo(resultsPaging);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Messages.
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public bool HasMessages()
|
||||||
|
{
|
||||||
|
return infoMessages.Count > 0 || warningMessages.Count > 0 || errorMessages.Count > 0;
|
||||||
|
}
|
||||||
|
public List<String> InfoMessages { get { return new List<string>(infoMessages); } }
|
||||||
|
public List<String> WarningMessages { get { return new List<string>(warningMessages); } }
|
||||||
|
public List<String> ErrorMessages { get { return new List<string>(errorMessages); } }
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Form messages.
|
||||||
|
public void AddInfoMessage(String message)
|
||||||
|
{
|
||||||
|
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||||
|
infoMessages.Add(message);
|
||||||
|
}
|
||||||
|
public void AddWarningMessage(String message)
|
||||||
|
{
|
||||||
|
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||||
|
warningMessages.Add(message);
|
||||||
|
}
|
||||||
|
public void AddErrorMessage(String message)
|
||||||
|
{
|
||||||
|
if (StringUtil.IsEmpty(StringUtil.TrimAll(message))) return;
|
||||||
|
errorMessages.Add(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
}
|
||||||
|
//=======================================================================
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,9 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
public String DateTimeSeparator { get; set; } = " ";
|
public String DateTimeSeparator { get; set; } = " ";
|
||||||
public String TimeFormat { get; set; } = "HH:mm";
|
public String TimeFormat { get; set; } = "HH:mm";
|
||||||
public DataValue.DataType DataType { get; set; } = DataValue.DataType.String;
|
public DataValue.DataType DataType { get; set; } = DataValue.DataType.String;
|
||||||
|
public bool IsNumeric { get { return DataType == DataValue.DataType.Long || DataType == DataValue.DataType.Double || DataType == DataValue.DataType.Decimal; } }
|
||||||
public bool Resizable { get; set; } = true;
|
public bool Resizable { get; set; } = true;
|
||||||
|
public bool WrapText { get; set; } = false;
|
||||||
public bool Hidden { get; set; } = false;
|
public bool Hidden { get; set; } = false;
|
||||||
public bool Frozen { get; set; } = false;
|
public bool Frozen { get; set; } = false;
|
||||||
// Drop-down configuration.
|
// Drop-down configuration.
|
||||||
@@ -107,12 +109,11 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
public bool ExclusiveValues { get; set; } = true;
|
public bool ExclusiveValues { get; set; } = true;
|
||||||
/// <summary>User entered values (Exclusive=false) are converted if corresponding value found in list.</summary>
|
/// <summary>User entered values (Exclusive=false) are converted if corresponding value found in list.</summary>
|
||||||
public bool MatchCase { get; set; } = true;
|
public bool MatchCase { get; set; } = true;
|
||||||
// Edit configuration:
|
// Edit configuration.
|
||||||
public int MaxLength { get; set; } = 0;
|
public int MaxLength { get; set; } = 0;
|
||||||
public bool ReadOnly { get; set; } = false;
|
public bool ReadOnly { get; set; } = false;
|
||||||
public bool Uppercase { get; set; } = false;
|
public bool Uppercase { get; set; } = false;
|
||||||
public bool Lowercase { get; set; } = false;
|
public bool Lowercase { get; set; } = false;
|
||||||
public bool Numeric { get; set; } = false;
|
|
||||||
public bool Password { get; set; } = false;
|
public bool Password { get; set; } = false;
|
||||||
// Sort attributes.
|
// Sort attributes.
|
||||||
/// <summary>Sort mode. Default: 'On'.</summary>
|
/// <summary>Sort mode. Default: 'On'.</summary>
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
}
|
}
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
/// <summary>Return value interpretted as boolean.</summary>
|
||||||
public bool ToBool ()
|
public bool ToBool ()
|
||||||
{
|
{
|
||||||
if (value == null) return false;
|
if (value == null) return false;
|
||||||
@@ -190,6 +191,7 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/// <summary>Return explicit boolean value or false for other types.</summary>
|
||||||
public bool AsBool ()
|
public bool AsBool ()
|
||||||
{
|
{
|
||||||
// Convert to specific type of data - fails if type is not correct:
|
// Convert to specific type of data - fails if type is not correct:
|
||||||
@@ -369,10 +371,58 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
|
// Data Value list extension functions.
|
||||||
|
|
||||||
public static class DataValueList
|
public static class DataValueList
|
||||||
{
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Population.
|
||||||
|
|
||||||
|
/// <summary>Add a String value to the list.</summary>
|
||||||
|
public static void Add(this List<DataValue> values, String value)
|
||||||
|
{
|
||||||
|
values.Add(new DataValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Add a boolean value to the list.</summary>
|
||||||
|
public static void Add(this List<DataValue> values, bool value)
|
||||||
|
{
|
||||||
|
values.Add(new DataValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Add an integer value to the list.</summary>
|
||||||
|
public static void Add(this List<DataValue> values, int value)
|
||||||
|
{
|
||||||
|
values.Add(new DataValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Add a long value to the list.</summary>
|
||||||
|
public static void Add(this List<DataValue> values, long value)
|
||||||
|
{
|
||||||
|
values.Add(new DataValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Add a double value to the list.</summary>
|
||||||
|
public static void Add(this List<DataValue> values, double value)
|
||||||
|
{
|
||||||
|
values.Add(new DataValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Add a decimal value to the list.</summary>
|
||||||
|
public static void Add(this List<DataValue> values, decimal value)
|
||||||
|
{
|
||||||
|
values.Add(new DataValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Add a date time value to the list.</summary>
|
||||||
|
public static void Add(this List<DataValue> values, DateTime value)
|
||||||
|
{
|
||||||
|
values.Add(new DataValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Conversion.
|
// Conversion.
|
||||||
|
|
||||||
/// <summary>Convert all data values to strings.</summary>
|
/// <summary>Convert all data values to strings.</summary>
|
||||||
public static List<String> ToStringList (this List<DataValue> values)
|
public static List<String> ToStringList (this List<DataValue> values)
|
||||||
{
|
{
|
||||||
@@ -381,6 +431,7 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
stringValues.Add(values.ToString());
|
stringValues.Add(values.ToString());
|
||||||
return stringValues;
|
return stringValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert the data values to raw objects.
|
/// Convert the data values to raw objects.
|
||||||
/// <para>eg. For population to Excel spreadsheet cells.</para>
|
/// <para>eg. For population to Excel spreadsheet cells.</para>
|
||||||
@@ -409,6 +460,7 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Numeric - only with compatible numeric values.
|
// Numeric - only with compatible numeric values.
|
||||||
|
|
||||||
/// <summary>Minimum numeric value in the list.</summary>
|
/// <summary>Minimum numeric value in the list.</summary>
|
||||||
public static DataValue GetMinValue (this List<DataValue> values)
|
public static DataValue GetMinValue (this List<DataValue> values)
|
||||||
{
|
{
|
||||||
@@ -425,6 +477,7 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
}
|
}
|
||||||
return minValue;
|
return minValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Maximum numeric value in the list.</summary>
|
/// <summary>Maximum numeric value in the list.</summary>
|
||||||
public static DataValue GetMaxValue (this List<DataValue> values)
|
public static DataValue GetMaxValue (this List<DataValue> values)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Sarand.Net.Standard.Base.Core
|
|||||||
// Disposal.
|
// Disposal.
|
||||||
~SacsDisposable ()
|
~SacsDisposable ()
|
||||||
{
|
{
|
||||||
Dispose(false);
|
Dispose(!disposed);
|
||||||
}
|
}
|
||||||
public void Dispose ()
|
public void Dispose ()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,8 +38,20 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
public new String PreferredContentType { set { base.PreferredContentType = value; } }
|
public new String PreferredContentType { set { base.PreferredContentType = value; } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Definitions.
|
||||||
|
/// <summary>Excel legacy - xls.</summary>
|
||||||
|
public static readonly String ContentType_Excel_Legacy = "application/vnd.ms-excel";
|
||||||
|
/// <summary>Excel open - xlsx.</summary>
|
||||||
|
public static readonly String ContentType_Excel_Open = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||||
|
/// <summary>Excel macro enabled - xlsm.</summary>
|
||||||
|
public static readonly String ContentType_Excel_MacroEnabled = "application/vnd.ms-excel.sheet.macroEnabled.12";
|
||||||
|
/// <summary>Excel binary macro enabled - xlsb.</summary>
|
||||||
|
public static readonly String ContentType_Excel_BinaryMacroEnabled = "application/vnd.ms-excel.sheet.binary.macroEnabled.12";
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
|
static String ContentType_Generic = "application/octet-stream";
|
||||||
private static readonly List<ContentTypeData> contentTypes;
|
private static readonly List<ContentTypeData> contentTypes;
|
||||||
private static FileExtensionContentTypeProvider provider = null;
|
private static FileExtensionContentTypeProvider provider = null;
|
||||||
private static readonly HashSet<Sacs.MimeType> allowedMimeTypes_CV = new HashSet<Sacs.MimeType>()
|
private static readonly HashSet<Sacs.MimeType> allowedMimeTypes_CV = new HashSet<Sacs.MimeType>()
|
||||||
@@ -87,8 +99,8 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
new ContentTypeData_Internal("docx", "Microsoft Word (OpenXML)", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", Sacs.MimeType.MsDocx),
|
new ContentTypeData_Internal("docx", "Microsoft Word (OpenXML)", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", Sacs.MimeType.MsDocx),
|
||||||
new ContentTypeData_Internal("odt", "OpenDocument text document", "application/vnd.oasis.opendocument.text", Sacs.MimeType.OpenDocText),
|
new ContentTypeData_Internal("odt", "OpenDocument text document", "application/vnd.oasis.opendocument.text", Sacs.MimeType.OpenDocText),
|
||||||
// Spreadsheets.
|
// Spreadsheets.
|
||||||
new ContentTypeData_Internal("xls", "Microsoft Excel", "application/vnd.ms-excel", Sacs.MimeType.MsXls),
|
new ContentTypeData_Internal("xls", "Microsoft Excel", ContentType_Excel_Legacy, Sacs.MimeType.MsXls),
|
||||||
new ContentTypeData_Internal("xlsx", "Microsoft Excel (OpenXML)", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Sacs.MimeType.MsXlsx),
|
new ContentTypeData_Internal("xlsx", "Microsoft Excel (OpenXML)", ContentType_Excel_Open, Sacs.MimeType.MsXlsx),
|
||||||
new ContentTypeData_Internal("ods", "OpenDocument spreadsheet document", "application/vnd.oasis.opendocument.spreadsheet", Sacs.MimeType.OpenDocSpreadsheet),
|
new ContentTypeData_Internal("ods", "OpenDocument spreadsheet document", "application/vnd.oasis.opendocument.spreadsheet", Sacs.MimeType.OpenDocSpreadsheet),
|
||||||
// Miscellaneous.
|
// Miscellaneous.
|
||||||
new ContentTypeData_Internal("aac", "AAC audio", "audio/aac"),
|
new ContentTypeData_Internal("aac", "AAC audio", "audio/aac"),
|
||||||
@@ -156,7 +168,7 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Properties.
|
// Properties.
|
||||||
/// <summary>Generic content type used for 'unknown' document types.</summary>
|
/// <summary>Generic content type used for 'unknown' document types.</summary>
|
||||||
public static String ContentTypeDefault { get; } = "application/octet-stream";
|
public static String ContentTypeDefault { get; } = ContentType_Generic;
|
||||||
/// <summary>Selection of comon content types.</summary>
|
/// <summary>Selection of comon content types.</summary>
|
||||||
public static List<ContentTypeData> ContentTypes { get { return new List<ContentTypeData>(contentTypes); } }
|
public static List<ContentTypeData> ContentTypes { get { return new List<ContentTypeData>(contentTypes); } }
|
||||||
public static FileExtensionContentTypeProvider Provider
|
public static FileExtensionContentTypeProvider Provider
|
||||||
@@ -223,6 +235,20 @@ namespace Sarand.Net.Standard.Base.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
/// <summary>Convert the enumerated Mime to content type.</summary>
|
||||||
|
public static String GetContentTypeFromMimeType(Sacs.MimeType mime)
|
||||||
|
{
|
||||||
|
if (mime == Sacs.MimeType.Unknown) return ContentTypeDefault;
|
||||||
|
ContentTypeData contentTypeData = contentTypes.Find(item => item.Mime.Equals(mime));
|
||||||
|
if (contentTypeData != null)
|
||||||
|
return contentTypeData.ContentType;
|
||||||
|
return ContentTypeDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Mime type.
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
/// <summary>Convert the content type to enumerated Mime.</summary>
|
/// <summary>Convert the content type to enumerated Mime.</summary>
|
||||||
public static Sacs.MimeType GetMimeTypeFromContentType(this String contentType)
|
public static Sacs.MimeType GetMimeTypeFromContentType(this String contentType)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,29 +1,37 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using Sarand.Net.Standard.Base.App;
|
using Sarand.Net.Standard.Base.App;
|
||||||
using Sarand.Net.Standard.Base.Core;
|
using Sarand.Net.Standard.Base.Core;
|
||||||
|
using Sarand.Net.Standard.Base.Tasks;
|
||||||
using Sarand.Net.Standard.Base.Utils;
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
using static Sarand.Net.Standard.Base.Procs.SaProcess_Base;
|
||||||
|
|
||||||
namespace Sarand.Net.Standard.Base.Procs
|
namespace Sarand.Net.Standard.Base.Procs
|
||||||
{
|
{
|
||||||
//=======================================================================
|
|
||||||
public interface ISacsProcessNotifier
|
|
||||||
{
|
|
||||||
void OnStartProcess ();
|
|
||||||
void SetProgressInfo (List<String> progressInfo);
|
|
||||||
void OnEndProcess ();
|
|
||||||
}
|
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
public abstract class SaProcess_Base : SacsDisposable
|
public abstract class SaProcess_Base : SacsDisposable
|
||||||
{
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Exceptions.
|
||||||
|
[Serializable]
|
||||||
|
public class InProgressException : Exception
|
||||||
|
{
|
||||||
|
public InProgressException() { }
|
||||||
|
public InProgressException(string message) : base(message) { }
|
||||||
|
public InProgressException(string message, Exception inner) : base(message, inner) { }
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Process options and groups - for configuration of process to run.
|
// Process options and groups - for configuration of process to run.
|
||||||
// See Sarand.Win.Forms.Utility.SaForm_SelectOptions.
|
// See Sarand.Win.Forms.Utility.SaForm_SelectOptions.
|
||||||
public class OptionData
|
public class OptionData
|
||||||
{
|
{
|
||||||
public OptionData (TypeCodeDesc option)
|
public OptionData(TypeCodeDesc option)
|
||||||
{
|
{
|
||||||
Option = option;
|
Option = option;
|
||||||
}
|
}
|
||||||
@@ -33,7 +41,7 @@ namespace Sarand.Net.Standard.Base.Procs
|
|||||||
}
|
}
|
||||||
public class GroupData
|
public class GroupData
|
||||||
{
|
{
|
||||||
public GroupData (TypeCodeDesc optionGroup)
|
public GroupData(TypeCodeDesc optionGroup)
|
||||||
{
|
{
|
||||||
OptionGroup = optionGroup;
|
OptionGroup = optionGroup;
|
||||||
}
|
}
|
||||||
@@ -55,13 +63,13 @@ namespace Sarand.Net.Standard.Base.Procs
|
|||||||
}
|
}
|
||||||
public class Config
|
public class Config
|
||||||
{
|
{
|
||||||
protected Config ()
|
protected Config()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/// <summary>Identifies the type of process.</summary>
|
/// <summary>Identifies the type of process.</summary>
|
||||||
public ProcessType ProcessType { get; set; } = ProcessType.Unknown;
|
public ProcessType ProcessType { get; set; } = ProcessType.Unknown;
|
||||||
/// <summary>Is the process to be run in 'Test' mode.</summary>
|
/// <summary>Is the process to be run in 'Test' mode.</summary>
|
||||||
public bool TestProcess{ get; set; } = SacsSystem.DebugMode;
|
public bool TestProcess { get; set; } = SacsSystem.DebugMode;
|
||||||
/// <summary>Process imports data.</summary>
|
/// <summary>Process imports data.</summary>
|
||||||
public bool Import { get { return ProcessType == ProcessType.ImportData || ProcessType == ProcessType.ImportExportData; } }
|
public bool Import { get { return ProcessType == ProcessType.ImportData || ProcessType == ProcessType.ImportExportData; } }
|
||||||
/// <summary>Process exports data.</summary>
|
/// <summary>Process exports data.</summary>
|
||||||
@@ -74,28 +82,131 @@ namespace Sarand.Net.Standard.Base.Procs
|
|||||||
public bool Automated { get; set; } = false;
|
public bool Automated { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Process control definitions.
|
||||||
|
|
||||||
|
public class ProcessMessage
|
||||||
|
{
|
||||||
|
public ProcessMessage(String message, SaMessageLevel level = SaMessageLevel.Info)
|
||||||
|
{
|
||||||
|
this.Message = message;
|
||||||
|
this.Level = level;
|
||||||
|
}
|
||||||
|
public String Message { get; }
|
||||||
|
public SaMessageLevel Level { get; }
|
||||||
|
public int Instances { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ProcessControlData
|
||||||
|
{
|
||||||
|
// Interrupt.
|
||||||
|
private class InterruptData
|
||||||
|
{
|
||||||
|
public readonly Object lockable = new object();
|
||||||
|
private bool interrupted = false;
|
||||||
|
public bool Interrupted { get { lock (lockable) { return interrupted; } } set { lock (lockable) { interrupted = value; } } }
|
||||||
|
}
|
||||||
|
private InterruptData interrupt { get; } = new InterruptData();
|
||||||
|
public bool Interrupted { get { return interrupt.Interrupted; } set { interrupt.Interrupted = value; } }
|
||||||
|
|
||||||
|
// Process messages.
|
||||||
|
private class ProcessMessagesData
|
||||||
|
{
|
||||||
|
public readonly Object lockable = new object();
|
||||||
|
public List<ProcessMessage> messages { get; } = new List<ProcessMessage>();
|
||||||
|
}
|
||||||
|
private ProcessMessagesData processMessages { get; } = new ProcessMessagesData();
|
||||||
|
/// <summary>Convert the message levele to one of the 3 values used with Process Messages: Info, Warning, Error.</summary>
|
||||||
|
public static SaMessageLevel GetLevel(SaMessageLevel level)
|
||||||
|
{
|
||||||
|
if (level == SaMessageLevel.Error || level == SaMessageLevel.Fatal || level == SaMessageLevel.Exception)
|
||||||
|
level = SaMessageLevel.Error;
|
||||||
|
else if (level == SaMessageLevel.Warning)
|
||||||
|
level = SaMessageLevel.Warning;
|
||||||
|
else
|
||||||
|
level = SaMessageLevel.Info;
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
/// <summary>Add a message of the specified level (Info, Warning, Error).</summary>
|
||||||
|
public bool AddProcessMessage(String message, SaMessageLevel level)
|
||||||
|
{
|
||||||
|
message = StringUtil.TrimWhitespace(message);
|
||||||
|
if (StringUtil.IsBlank(message)) return false;
|
||||||
|
level = GetLevel(level);
|
||||||
|
lock (processMessages.lockable)
|
||||||
|
{
|
||||||
|
ProcessMessage procMsg = processMessages.messages.Find(item => item.Message.EqualsCI(message) && item.Level == level);
|
||||||
|
// Duplicate messages increment the 'Instances' value.
|
||||||
|
if (procMsg != null)
|
||||||
|
procMsg.Instances++;
|
||||||
|
// Otherwise add a new message to the list.
|
||||||
|
else processMessages.messages.Add(new ProcessMessage(message, level));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/// <summary>Are there any message of the specified level (Info, Warning, Error).</summary>
|
||||||
|
public bool HasProcessMessages(SaMessageLevel level)
|
||||||
|
{
|
||||||
|
lock (processMessages.lockable)
|
||||||
|
return processMessages.messages.Exists(item => item.Level == GetLevel(level));
|
||||||
|
}
|
||||||
|
/// <summary>Get the first message of the specified level (Info, Warning, Error).</summary>
|
||||||
|
public String GetProcessMessage(SaMessageLevel level)
|
||||||
|
{
|
||||||
|
lock (processMessages.lockable)
|
||||||
|
return processMessages.messages.Find(item => item.Level == GetLevel(level))?.Message ?? "";
|
||||||
|
}
|
||||||
|
/// <summary>Return all process messages.</summary>
|
||||||
|
public List<ProcessMessage> GetProcessMessages()
|
||||||
|
{
|
||||||
|
List<ProcessMessage> messages = new List<ProcessMessage>();
|
||||||
|
lock (processMessages.lockable)
|
||||||
|
messages.AddRange(processMessages.messages);
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
/// <summary>Return all process messages of the specified Level (Info, Warning, Error).</summary>
|
||||||
|
public List<ProcessMessage> GetProcessMessages(SaMessageLevel level)
|
||||||
|
{
|
||||||
|
List<ProcessMessage> messages = new List<ProcessMessage>();
|
||||||
|
lock (processMessages.lockable)
|
||||||
|
messages.AddRange(processMessages.messages.FindAll(item => item.Level == GetLevel(level)));
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
/// <summary>Clear process messages.</summary>
|
||||||
|
public void ClearProcessMessages()
|
||||||
|
{
|
||||||
|
lock (processMessages.lockable)
|
||||||
|
processMessages.messages.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task control data.
|
||||||
|
private SacsTaskData taskData = null;
|
||||||
|
public SacsTaskData TaskData { get { return taskData; } set { if (taskData != null) taskData.Dispose(); taskData = value; } }
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
private Config config;
|
private Config config;
|
||||||
private String processError = "";
|
private ProcessControlData Control { get; } = new ProcessControlData();
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Construction.
|
// Construction.
|
||||||
protected SaProcess_Base (Config config)
|
protected SaProcess_Base(Config config)
|
||||||
{
|
{
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
protected override void Dispose (bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
// Clear process data to dispose.
|
||||||
|
Control.TaskData = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Properties.
|
// Properties.
|
||||||
public bool DebugMode { get { return SacsSystem.DebugMode; } }
|
public bool DebugMode { get { return SacsSystem.DebugMode; } }
|
||||||
public ISacsProcessNotifier ProcessNotifier { get; set; } = null;
|
|
||||||
public bool Processing { get; protected set; } = false;
|
public bool Processing { get; protected set; } = false;
|
||||||
public bool ProcessEnded { get; protected set; } = false;
|
public bool ProcessEnded { get; protected set; } = false;
|
||||||
public DateTime StartedAt { get; private set; } = DateTime.MinValue;
|
public DateTime StartedAt { get; private set; } = DateTime.MinValue;
|
||||||
@@ -120,56 +231,195 @@ namespace Sarand.Net.Standard.Base.Procs
|
|||||||
public virtual List<StringPair> ProcessingStatistics { get { return new List<StringPair>(); } }
|
public virtual List<StringPair> ProcessingStatistics { get { return new List<StringPair>(); } }
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Run process inline.
|
// Run process asynchronously.
|
||||||
public bool RunProcess ()
|
private class AsyncProcessData : SacsDisposable
|
||||||
{
|
{
|
||||||
String fn = GetType().Name+".RunProcess";
|
public AsyncProcessData(Task task)
|
||||||
if (ProcessNotifier == null)
|
{
|
||||||
throw new NotSupportedException("Process Notifier must be specified");
|
this.Task = task;
|
||||||
|
}
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing) { }
|
||||||
|
}
|
||||||
|
public Task Task { get; }
|
||||||
|
}
|
||||||
|
private AsyncProcessData AsyncData { get; set; }
|
||||||
|
public bool IsAsync { get { return AsyncData != null; } }
|
||||||
|
private void ClearAsyncData()
|
||||||
|
{
|
||||||
|
if (AsyncData != null)
|
||||||
|
{
|
||||||
|
lock (AsyncData)
|
||||||
|
{
|
||||||
|
AsyncData.Dispose();
|
||||||
|
AsyncData = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Run the process asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="InProgressException">If process is already running.</exception>
|
||||||
|
public async void RunAsync()
|
||||||
|
{
|
||||||
|
if (AsyncData != null)
|
||||||
|
throw new InProgressException();
|
||||||
|
Control.TaskData = new SacsTaskData();
|
||||||
|
// Run on separate thread.
|
||||||
|
Task task = new Task(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Execute the process.
|
||||||
|
RunProcess();
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException exc)
|
||||||
|
{
|
||||||
|
SaLogger.Warn(exc.GetType().Name + " during asynchronous processing on " + GetType().Name);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Clear processing data.
|
||||||
|
ClearAsyncData();
|
||||||
|
}
|
||||||
|
}, Control.TaskData.CancellationToken);
|
||||||
|
AsyncData = new AsyncProcessData(task);
|
||||||
|
task.Start();
|
||||||
|
await task;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Run process inline.
|
||||||
|
public bool RunProcess()
|
||||||
|
{
|
||||||
|
String fn = GetType().Name + ".RunProcess";
|
||||||
// Prepare process.
|
// Prepare process.
|
||||||
bool runProcess = false;
|
bool runProcess = false;
|
||||||
Reset();
|
Reset();
|
||||||
|
if (Control.TaskData == null)
|
||||||
|
Control.TaskData = new SacsTaskData();
|
||||||
Processing = true;
|
Processing = true;
|
||||||
StartedAt = DateTime.Now;
|
StartedAt = DateTime.Now;
|
||||||
|
|
||||||
|
// Process starting.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Notify start of process and log/ignore exceptions.
|
// Notify start of process and log/ignore exceptions.
|
||||||
ProcessNotifier.OnStartProcess();
|
InvokeProcessStarting();
|
||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SaLogger.Error(fn + " OnStartProcess: " + GetProcessError() + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
String msg = exc.GetType().Name + ": " + exc.Message;
|
||||||
|
AddErrorMessage(msg);
|
||||||
|
SaLogger.Error(fn + " ProcessStarting: " + msg + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process running.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Run process.
|
// Run process.
|
||||||
OnProcessStarting();
|
|
||||||
runProcess = Run();
|
runProcess = Run();
|
||||||
OnProcessEnding();
|
|
||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SetProcessError(exc.GetType().Name + ": " + exc.Message);
|
String msg = exc.GetType().Name + ": " + exc.Message;
|
||||||
SaLogger.Error(fn + " " + GetProcessError() + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
AddErrorMessage(msg);
|
||||||
|
SaLogger.Error(fn + " " + msg + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
// Processing completed.
|
// Processing completed.
|
||||||
FinishedAt = DateTime.Now;
|
FinishedAt = DateTime.Now;
|
||||||
Processing = false;
|
Processing = false;
|
||||||
ProcessEnded = true;
|
ProcessEnded = true;
|
||||||
|
Control.TaskData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process completed.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Notify end of process and log/ignore exceptions.
|
// Notify completion of process and log/ignore exceptions.
|
||||||
ProcessNotifier.OnEndProcess();
|
InvokeProcessCompleted();
|
||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SaLogger.Error(fn + " OnEndProcess: " + GetProcessError() + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
String msg = exc.GetType().Name + ": " + exc.Message;
|
||||||
|
AddErrorMessage(msg);
|
||||||
|
SaLogger.Error(fn + " ProcessCompleted: " + msg + exc.GetStackEntries(6).Concat("", "\n\tat "), true);
|
||||||
}
|
}
|
||||||
return runProcess;
|
return runProcess;
|
||||||
}
|
}
|
||||||
protected abstract bool Run ();
|
protected abstract bool Run();
|
||||||
protected virtual void OnProcessStarting () { }
|
|
||||||
protected virtual void OnProcessEnding () { }
|
//-------------------------------------------------------------------
|
||||||
|
public async Task StopProcessAsync(int timeout = 50)
|
||||||
|
{
|
||||||
|
if (!Processing) return;
|
||||||
|
if (AsyncData != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Cancel the task.
|
||||||
|
Control.TaskData.TriggerCancellation();
|
||||||
|
// Wait for task termination or timeout.
|
||||||
|
if (await Task.WhenAny(AsyncData.Task, Task.Delay(Math.Max(20, Math.Min(1000, timeout)))) != AsyncData.Task)
|
||||||
|
{
|
||||||
|
// Timeout completed before task - force termination.
|
||||||
|
Control.TaskData.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Control.TaskData = null;
|
||||||
|
ClearAsyncData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Processing events.
|
||||||
|
|
||||||
|
// Processing Starting.
|
||||||
|
public class ProcessStartingEventArgs : EventArgs { }
|
||||||
|
public event EventHandler<ProcessStartingEventArgs> OnProcessStarting;
|
||||||
|
protected virtual void InvokeProcessStarting()
|
||||||
|
{
|
||||||
|
if (OnProcessStarting != null)
|
||||||
|
{
|
||||||
|
ProcessStartingEventArgs args = new ProcessStartingEventArgs();
|
||||||
|
OnProcessStarting(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process Info Updated.
|
||||||
|
public class ProgressInfoUpdatedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public List<String> ProgressInfo { get; } = new List<string>();
|
||||||
|
}
|
||||||
|
public event EventHandler<ProgressInfoUpdatedEventArgs> OnProgressInfoUpdated;
|
||||||
|
protected virtual void InvokeProgressInfoUpdated(List<String> progressInfo)
|
||||||
|
{
|
||||||
|
if (OnProgressInfoUpdated != null)
|
||||||
|
{
|
||||||
|
ProgressInfoUpdatedEventArgs args = new ProgressInfoUpdatedEventArgs();
|
||||||
|
args.ProgressInfo.AddRange(progressInfo);
|
||||||
|
OnProgressInfoUpdated(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processing Completed.
|
||||||
|
public class ProcessCompletedEventArgs : EventArgs { }
|
||||||
|
public event EventHandler<ProcessCompletedEventArgs> OnProcessCompleted;
|
||||||
|
protected virtual void InvokeProcessCompleted()
|
||||||
|
{
|
||||||
|
if (OnProcessCompleted != null)
|
||||||
|
{
|
||||||
|
ProcessCompletedEventArgs args = new ProcessCompletedEventArgs();
|
||||||
|
OnProcessCompleted(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Process control.
|
// Process control.
|
||||||
@@ -177,15 +427,15 @@ namespace Sarand.Net.Standard.Base.Procs
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (HasProcessError()) return false;
|
if (HasErrorMessage()) return false;
|
||||||
if (isInterrupted) return false;
|
if (Control.Interrupted) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void Reset ()
|
private void Reset()
|
||||||
{
|
{
|
||||||
ClearProcessError();
|
Control.ClearProcessMessages();
|
||||||
isInterrupted = false;
|
Control.Interrupted = false;
|
||||||
ProcessEnded = false;
|
ProcessEnded = false;
|
||||||
StartedAt = DateTime.MinValue;
|
StartedAt = DateTime.MinValue;
|
||||||
FinishedAt = DateTime.MinValue;
|
FinishedAt = DateTime.MinValue;
|
||||||
@@ -193,36 +443,70 @@ namespace Sarand.Net.Standard.Base.Procs
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Progress information.
|
// Progress information.
|
||||||
protected void SetProgressInfo (String progressInfo)
|
protected void SetProgressInfo(String progressInfo)
|
||||||
{
|
{
|
||||||
SetProgressInfo(StringListUtil.CreateList(progressInfo));
|
SetProgressInfo(StringListUtil.CreateList(progressInfo));
|
||||||
}
|
}
|
||||||
protected void SetProgressInfo (List<String> progressInfo)
|
protected void SetProgressInfo(List<String> progressInfo)
|
||||||
{
|
{
|
||||||
if (ProcessNotifier != null)
|
InvokeProgressInfoUpdated(progressInfo);
|
||||||
ProcessNotifier.SetProgressInfo(progressInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Error handling.
|
// Process messages.
|
||||||
public bool HasProcessError () { return !StringUtil.IsEmpty(processError); }
|
/// <summary>Add a message of the specified level (Info, Warning, Error).</summary>
|
||||||
public String GetProcessError () { return StringUtil.EmptyOnNull(processError); }
|
protected void AddMessage(String message, SaMessageLevel level)
|
||||||
public void ClearProcessError () { processError = ""; }
|
|
||||||
/// <summary>Record the processing error - always returns false.</summary>
|
|
||||||
public bool SetProcessError (String error)
|
|
||||||
{
|
{
|
||||||
processError = StringUtil.EmptyOnNull(error);
|
if (Control.AddProcessMessage(message, level))
|
||||||
|
SaLogger.Log(GetType().Name + " " + message, ProcessControlData.GetLevel(level));
|
||||||
|
}
|
||||||
|
protected void AddInfoMessage(String message)
|
||||||
|
{
|
||||||
|
AddMessage(message, SaMessageLevel.Info);
|
||||||
|
}
|
||||||
|
protected void AddWarningMessage(String message)
|
||||||
|
{
|
||||||
|
AddMessage(message, SaMessageLevel.Warning);
|
||||||
|
}
|
||||||
|
/// <summary>Add the error message and always return false.</summary>
|
||||||
|
protected bool AddErrorMessage(String message)
|
||||||
|
{
|
||||||
|
AddMessage(message, SaMessageLevel.Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/// <summary>Are there any error messages.</summary>
|
||||||
|
public bool HasErrorMessage()
|
||||||
|
{
|
||||||
|
return Control.HasProcessMessages(SaMessageLevel.Error);
|
||||||
|
}
|
||||||
|
/// <summary>Get the first error message.</summary>
|
||||||
|
public String GetErrorMessage()
|
||||||
|
{
|
||||||
|
return Control.GetProcessMessage(SaMessageLevel.Error);
|
||||||
|
}
|
||||||
|
/// <summary>Return all process messages.</summary>
|
||||||
|
public List<ProcessMessage> GetProcessMessages()
|
||||||
|
{
|
||||||
|
return Control.GetProcessMessages();
|
||||||
|
}
|
||||||
|
/// <summary>Return all process messages of the specified Level (Info, Warning, Error).</summary>
|
||||||
|
public List<ProcessMessage> GetProcessMessages(SaMessageLevel level)
|
||||||
|
{
|
||||||
|
return Control.GetProcessMessages(level);
|
||||||
|
}
|
||||||
|
/// <summary>Clear process messages.</summary>
|
||||||
|
public void ClearProcessMessages()
|
||||||
|
{
|
||||||
|
Control.ClearProcessMessages();
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Interruption.
|
// Interruption.
|
||||||
private bool isInterrupted = false;
|
|
||||||
public bool IsInterrupted
|
public bool IsInterrupted
|
||||||
{
|
{
|
||||||
get { return isInterrupted; }
|
get { return Control.Interrupted; }
|
||||||
}
|
}
|
||||||
public bool Interrupt ()
|
public bool Interrupt()
|
||||||
{
|
{
|
||||||
if (!config.AllowInterruption)
|
if (!config.AllowInterruption)
|
||||||
{
|
{
|
||||||
@@ -230,10 +514,10 @@ namespace Sarand.Net.Standard.Base.Procs
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (config.ConfirmInterruption && !IsInterruptionConfirmed()) return false;
|
if (config.ConfirmInterruption && !IsInterruptionConfirmed()) return false;
|
||||||
isInterrupted = true;
|
Control.Interrupted = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
protected virtual bool IsInterruptionConfirmed ()
|
protected virtual bool IsInterruptionConfirmed()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Sarand.Net.Standard.Base.Tasks
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Construction.
|
// Construction.
|
||||||
public SacsTaskData (CancellationToken? cancellationToken)
|
public SacsTaskData (CancellationToken? cancellationToken = null)
|
||||||
{
|
{
|
||||||
if (cancellationToken != null)
|
if (cancellationToken != null)
|
||||||
{
|
{
|
||||||
@@ -49,18 +49,22 @@ namespace Sarand.Net.Standard.Base.Tasks
|
|||||||
// Properties.
|
// Properties.
|
||||||
public bool Debug { get; set; }
|
public bool Debug { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Token to allow the async request to be cancelled.</summary>
|
||||||
|
public CancellationToken CancellationToken { get; }
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// C a n c e l l a t i o n
|
// C a n c e l l a t i o n
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
/// <summary>Token to allow the async request to be cancelled.</summary>
|
|
||||||
public CancellationToken CancellationToken { get; }
|
|
||||||
/// <summary>Gets whether cancellation has been requested.</summary>
|
/// <summary>Gets whether cancellation has been requested.</summary>
|
||||||
public bool IsCancellationRequested { get { return CancellationToken.IsCancellationRequested; } }
|
public bool IsCancellationRequested { get { return CancellationToken.IsCancellationRequested; } }
|
||||||
|
|
||||||
/// <summary>Throws a System.OperationCanceledException if this token has had cancellation requested.</summary>
|
/// <summary>Throws a System.OperationCanceledException if this token has had cancellation requested.</summary>
|
||||||
public void ThrowIfCancellationRequested()
|
public void ThrowIfCancellationRequested()
|
||||||
{
|
{
|
||||||
CancellationToken.ThrowIfCancellationRequested();
|
CancellationToken.ThrowIfCancellationRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Can cancellation be triggered here?</summary>
|
/// <summary>Can cancellation be triggered here?</summary>
|
||||||
public bool CanBeCancelled { get { return cancellationTokenSource != null; } }
|
public bool CanBeCancelled { get { return cancellationTokenSource != null; } }
|
||||||
public bool TriggerCancellation ()
|
public bool TriggerCancellation ()
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static SixLabors.ImageSharp.Image LoadImage(byte[] imageData, out IImageFormat format)
|
public static SixLabors.ImageSharp.Image LoadImage(byte[] imageData, out IImageFormat format)
|
||||||
{
|
{
|
||||||
var image = Image.Load<Rgba32>(imageData, out format);
|
var image = Image.Load<Rgba32>(imageData);
|
||||||
|
format = Image.DetectFormat(imageData);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
{
|
{
|
||||||
using (MemoryStream ms = new MemoryStream())
|
using (MemoryStream ms = new MemoryStream())
|
||||||
{
|
{
|
||||||
var imageEncoder = image.GetConfiguration().ImageFormatsManager.FindEncoder(imageFormat);
|
var imageEncoder = image.Configuration.ImageFormatsManager.GetEncoder(imageFormat);
|
||||||
image.Save(ms, imageEncoder);
|
image.Save(ms, imageEncoder);
|
||||||
return ms.ToArray();
|
return ms.ToArray();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
@@ -26,32 +27,24 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
if (Object.ReferenceEquals(source, null))
|
if (Object.ReferenceEquals(source, null))
|
||||||
return default(T);
|
return default(T);
|
||||||
|
|
||||||
IFormatter formatter = new BinaryFormatter();
|
// initialize inner objects individually
|
||||||
Stream stream = new MemoryStream();
|
// for example in default constructor some list property initialized with some values,
|
||||||
using (stream)
|
// but in 'source' these items are cleaned -
|
||||||
{
|
// without ObjectCreationHandling.Replace default constructor values will be added to result
|
||||||
formatter.Serialize(stream, source);
|
var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
|
||||||
stream.Seek(0, SeekOrigin.Begin);
|
|
||||||
return (T)formatter.Deserialize(stream);
|
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Serialize.
|
// Serialize using JSON.
|
||||||
public static String Serialize<T>(T source)
|
public static String ToJson<T>(T source)
|
||||||
{
|
{
|
||||||
if (!typeof(T).IsSerializable) throw new ArgumentException("The type must be serializable.", "source");
|
if (!typeof(T).IsSerializable) throw new ArgumentException("The type must be serializable.", "source");
|
||||||
// Don't serialize a null object, simply return the default for that object
|
// Don't serialize a null object, simply return the default for that object
|
||||||
if (Object.ReferenceEquals(source, null)) return "";
|
if (Object.ReferenceEquals(source, null)) return "";
|
||||||
// Serialise to String.
|
// Serialise to JSON String.
|
||||||
IFormatter formatter = new BinaryFormatter();
|
return JsonConvert.SerializeObject(source);
|
||||||
using (Stream stream = new MemoryStream())
|
|
||||||
using (StreamReader streamReader = new StreamReader(stream))
|
|
||||||
{
|
|
||||||
formatter.Serialize(stream, source);
|
|
||||||
stream.Seek(0, SeekOrigin.Begin);
|
|
||||||
return streamReader.ReadToEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -231,7 +231,20 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
Regex regexMultipleInternal = new Regex("[" + Regex.Escape(new String(trimChars)) + "]{2,}", RegexOptions.None);
|
Regex regexMultipleInternal = new Regex("[" + Regex.Escape(new String(trimChars)) + "]{2,}", RegexOptions.None);
|
||||||
return regexMultipleInternal.Replace(value, replacement);
|
return regexMultipleInternal.Replace(value, replacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Regex regexWhitespace = new Regex("\\s+", RegexOptions.Compiled);
|
||||||
|
/// <summary>
|
||||||
|
/// Trim all leading and trailling whitespace and replace internal whitespace with a single space.
|
||||||
|
/// </summary>
|
||||||
|
public static String TrimWhitespace(this String value)
|
||||||
|
{
|
||||||
|
return regexWhitespace.Replace(value, " ").Trim();
|
||||||
|
}
|
||||||
|
|
||||||
private static Regex regexMultipleSpaces = new Regex("[ ]{2,}", RegexOptions.Compiled);
|
private static Regex regexMultipleSpaces = new Regex("[ ]{2,}", RegexOptions.Compiled);
|
||||||
|
/// <summary>
|
||||||
|
/// Replace multiple spaces with a single space.
|
||||||
|
/// </summary>
|
||||||
public static String TrimInternalSpaces(this String value)
|
public static String TrimInternalSpaces(this String value)
|
||||||
{
|
{
|
||||||
return regexMultipleSpaces.Replace(value, " ");
|
return regexMultipleSpaces.Replace(value, " ");
|
||||||
@@ -540,6 +553,7 @@ namespace Sarand.Net.Standard.Base.Utils
|
|||||||
if (value.ToDouble() != 0.0) return true;
|
if (value.ToDouble() != 0.0) return true;
|
||||||
if (value.Left(1).EqualsCI("Y")) return true;
|
if (value.Left(1).EqualsCI("Y")) return true;
|
||||||
if (value.EqualsCI("True")) return true;
|
if (value.EqualsCI("True")) return true;
|
||||||
|
if (value.EqualsCI("On")) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,82 @@
|
|||||||
namespace Sarand.Net.Standard.Base.Utils
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Sarand.Net.Standard.Base.Utils
|
||||||
{
|
{
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
public class SysUtil
|
public static class SysUtil
|
||||||
{
|
{
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
/// <summary>Get calling code's class name.</summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public static string GetCallerClassName()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stackFrame = new StackTrace().GetFrame(1);
|
||||||
|
var methodInfo = stackFrame.GetMethod();
|
||||||
|
return methodInfo.ReflectedType.Name.TrimWhitespace();
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Get calling code's fucntion name.</summary>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public static string GetCallerMemberName([CallerMemberName] string memberName = "")
|
||||||
|
{
|
||||||
|
return memberName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Get calling code's file path.</summary>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public static string GetCallerFilePath([CallerFilePath] string filePath = "")
|
||||||
|
{
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Get calling code's line number.</summary>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public static int GetCallerLineNumber([CallerLineNumber] int lineNumber = 0)
|
||||||
|
{
|
||||||
|
return lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Construction.
|
/// <summary>Shortcut to GetCallerClassMethod() - returns [class.method] for calling code.</summary>
|
||||||
private SysUtil () { }
|
public static string Fn { get { return GetCallerClassMethod(2); } }
|
||||||
|
|
||||||
|
/// <summary>Return identity of calling method as [class.method].</summary>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public static string GetCallerClassMethod(int stackFrameIdx = 1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stackFrame = new StackTrace().GetFrame(stackFrameIdx);
|
||||||
|
var methodInfo = stackFrame.GetMethod();
|
||||||
|
return (methodInfo.ReflectedType.Name + "." + methodInfo.Name).TrimWhitespace().Trim('.');
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>Return identity of calling method as [class.method:line].</summary>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public static string GetCallerClassMethodLine()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stackFrame = new StackTrace().GetFrame(1);
|
||||||
|
var methodInfo = stackFrame.GetMethod();
|
||||||
|
return (methodInfo.ReflectedType.Name + "." + methodInfo.Name + ":" + stackFrame.GetFileLineNumber()).TrimWhitespace().Trim('.');
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CsvHelper" Version="19.0.0" />
|
<PackageReference Include="CsvHelper" Version="19.0.0" />
|
||||||
<PackageReference Include="MailKit" Version="2.11.1" />
|
<PackageReference Include="MailKit" Version="2.15.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.1" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Construction.
|
// Construction.
|
||||||
public SaDbDfnOdbcDriver (String name)
|
public SaDbDfnOdbcDriver(String name)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
||||||
@@ -25,16 +25,17 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Properties.
|
// Properties.
|
||||||
public String Name { get; }
|
public String Name { get; }
|
||||||
public Dictionary<String,String> Attributes { get; } = new Dictionary<String, String>();
|
public Dictionary<String, String> Attributes { get; } = new Dictionary<String, String>();
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Utilities.
|
// Utilities.
|
||||||
/// <summary>Add 'Driver' attribute from registry. Fails if driver name not found.</summary>
|
/// <summary>Add 'Driver' attribute from registry. Fails if driver name not found.</summary>
|
||||||
public bool AddDriverConfig ()
|
public bool AddDriverConfig()
|
||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(Name)) return false;
|
if (StringUtil.IsEmpty(Name)) return false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CA1416
|
||||||
// Retrieve 'Driver' (location of DLL) parameter for this driver:
|
// Retrieve 'Driver' (location of DLL) parameter for this driver:
|
||||||
using (RegistryKey localMachineHive = Registry.LocalMachine)
|
using (RegistryKey localMachineHive = Registry.LocalMachine)
|
||||||
using (RegistryKey odbcDriverKey = localMachineHive.OpenSubKey(@"SOFTWARE\ODBC\ODBCINST.INI\" + Name))
|
using (RegistryKey odbcDriverKey = localMachineHive.OpenSubKey(@"SOFTWARE\ODBC\ODBCINST.INI\" + Name))
|
||||||
@@ -47,6 +48,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
catch (Exception) { }
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Construction.
|
// Construction.
|
||||||
protected SacsDatabase (DbmsType dbms, String databaseName, String connectionString)
|
protected SacsDatabase(DbmsType dbms, String databaseName, String connectionString)
|
||||||
{
|
{
|
||||||
DbmsType = dbms;
|
DbmsType = dbms;
|
||||||
DatabaseName = databaseName;
|
DatabaseName = databaseName;
|
||||||
@@ -36,9 +36,9 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
public String DatabaseName { get; }
|
public String DatabaseName { get; }
|
||||||
public SelectLockMode SelectLockMode { get; set; } = SelectLockMode.Default;
|
public SelectLockMode SelectLockMode { get; set; } = SelectLockMode.Default;
|
||||||
public bool DisplayErrors { get; set; } = true;
|
public bool DisplayErrors { get; set; } = true;
|
||||||
public abstract void OnConnectionChanged ();
|
public abstract void OnConnectionChanged();
|
||||||
public abstract DbConnection CreateConnection (bool forceOdbc = false);
|
public abstract DbConnection CreateConnection(bool forceOdbc = false);
|
||||||
public abstract DbDataAdapter CreateDataAdapter ();
|
public abstract DbDataAdapter CreateDataAdapter();
|
||||||
// Profile properties.
|
// Profile properties.
|
||||||
public static String ProfileSection_DbUtilities { get; } = "DbUtilities";
|
public static String ProfileSection_DbUtilities { get; } = "DbUtilities";
|
||||||
public static String ProfileValue_DbExportFile { get; } = "DbExportFile";
|
public static String ProfileValue_DbExportFile { get; } = "DbExportFile";
|
||||||
@@ -57,21 +57,21 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
protected String NextIdTable { get; set; } = "NextId";
|
protected String NextIdTable { get; set; } = "NextId";
|
||||||
protected String NextIdColumn_Object { get; set; } = "Object";
|
protected String NextIdColumn_Object { get; set; } = "Object";
|
||||||
protected String NextIdColumn_NextId { get; set; } = "NextId";
|
protected String NextIdColumn_NextId { get; set; } = "NextId";
|
||||||
public abstract SysId GetNextId (String objectName, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id");
|
public abstract SysId GetNextId(String objectName, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id");
|
||||||
public abstract int GetNextIdFromTable(string objectName, string idColumn = "Id");
|
public abstract int GetNextIdFromTable(string objectName, string idColumn = "Id");
|
||||||
public abstract bool SetMinNextId (String objectName, SysId id, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id", bool force = false);
|
public abstract bool SetMinNextId(String objectName, SysId id, DbUpdateInfo dbUpdateInfo, bool databaseTable = true, String idColumn = "Id", bool force = false);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// O D B C D r i v e r s
|
// O D B C D r i v e r s
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
[DllImport("odbccp32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
[DllImport("odbccp32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
private static extern bool SQLGetInstalledDriversW (char[] lpszBuf, ushort cbufMax, out ushort pcbBufOut);
|
private static extern bool SQLGetInstalledDriversW(char[] lpszBuf, ushort cbufMax, out ushort pcbBufOut);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the ODBC driver names from the SQLGetInstalledDrivers function.
|
/// Gets the ODBC driver names from the SQLGetInstalledDrivers function.
|
||||||
/// <para>Ref. https://stackoverflow.com/questions/6457973/odbc-driver-list-from-net</para>
|
/// <para>Ref. https://stackoverflow.com/questions/6457973/odbc-driver-list-from-net</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>List of ODBC driver names, if successfull.</returns>
|
/// <returns>List of ODBC driver names, if successfull.</returns>
|
||||||
public static List<String> GetOdbcDriverNames ()
|
public static List<String> GetOdbcDriverNames()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -93,13 +93,16 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
catch (Exception) { }
|
catch (Exception) { }
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CA1416
|
||||||
// Alternatively, use the registry.
|
// Alternatively, use the registry.
|
||||||
|
// Validate platform compatibility
|
||||||
using (RegistryKey localMachineHive = Registry.LocalMachine)
|
using (RegistryKey localMachineHive = Registry.LocalMachine)
|
||||||
using (RegistryKey odbcDriversKey = localMachineHive.OpenSubKey(@"SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers"))
|
using (RegistryKey odbcDriversKey = localMachineHive.OpenSubKey(@"SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers"))
|
||||||
{
|
{
|
||||||
if (odbcDriversKey != null)
|
if (odbcDriversKey != null)
|
||||||
return new List<String>(odbcDriversKey.GetValueNames()).OrderBy(item => item).ToList();
|
return new List<String>(odbcDriversKey.GetValueNames()).OrderBy(item => item).ToList();
|
||||||
}
|
}
|
||||||
|
// Validate platform compatibility
|
||||||
// 64-BitConverter machines.
|
// 64-BitConverter machines.
|
||||||
using (RegistryKey localMachineHive = Registry.LocalMachine)
|
using (RegistryKey localMachineHive = Registry.LocalMachine)
|
||||||
using (RegistryKey odbcDriversKey = localMachineHive.OpenSubKey(@"SOFTWARE\Wow6432Node\ODBC\ODBCINST.INI\ODBC Drivers"))
|
using (RegistryKey odbcDriversKey = localMachineHive.OpenSubKey(@"SOFTWARE\Wow6432Node\ODBC\ODBCINST.INI\ODBC Drivers"))
|
||||||
@@ -107,6 +110,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
if (odbcDriversKey != null)
|
if (odbcDriversKey != null)
|
||||||
return new List<String>(odbcDriversKey.GetValueNames()).OrderBy(item => item).ToList();
|
return new List<String>(odbcDriversKey.GetValueNames()).OrderBy(item => item).ToList();
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CA1416
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
catch (Exception) { }
|
||||||
return new List<String>();
|
return new List<String>();
|
||||||
@@ -116,13 +120,13 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
// O D B C D a t a S o u r c e s
|
// O D B C D a t a S o u r c e s
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
[DllImport("odbc32.dll")]
|
[DllImport("odbc32.dll")]
|
||||||
public static extern int SQLDataSources (int EnvHandle, int Direction, StringBuilder ServerName, int ServerNameBufferLenIn, ref int ServerNameBufferLenOut, StringBuilder Driver, int DriverBufferLenIn, ref int DriverBufferLenOut);
|
public static extern int SQLDataSources(int EnvHandle, int Direction, StringBuilder ServerName, int ServerNameBufferLenIn, ref int ServerNameBufferLenOut, StringBuilder Driver, int DriverBufferLenIn, ref int DriverBufferLenOut);
|
||||||
[DllImport("odbc32.dll")]
|
[DllImport("odbc32.dll")]
|
||||||
public static extern int SQLAllocEnv (ref int EnvHandle);
|
public static extern int SQLAllocEnv(ref int EnvHandle);
|
||||||
public static List<SaDbDfnOdbcDataSource> GetOdbcDatasources ()
|
public static List<SaDbDfnOdbcDataSource> GetOdbcDatasources()
|
||||||
{
|
{
|
||||||
List<SaDbDfnOdbcDataSource> dataSources = new List<SaDbDfnOdbcDataSource>();
|
List<SaDbDfnOdbcDataSource> dataSources = new List<SaDbDfnOdbcDataSource>();
|
||||||
int envHandle=0;
|
int envHandle = 0;
|
||||||
const int SQL_FETCH_NEXT = 1;
|
const int SQL_FETCH_NEXT = 1;
|
||||||
const int SQL_FETCH_FIRST_SYSTEM = 32;
|
const int SQL_FETCH_FIRST_SYSTEM = 32;
|
||||||
|
|
||||||
@@ -147,7 +151,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Q u e r y D a t a b a s e
|
// Q u e r y D a t a b a s e
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public String GetSelectQueryPrefix ()
|
public String GetSelectQueryPrefix()
|
||||||
{
|
{
|
||||||
// Query prefix.
|
// Query prefix.
|
||||||
switch (SelectLockMode)
|
switch (SelectLockMode)
|
||||||
@@ -180,16 +184,16 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
public abstract IDbDataTable ExecuteQuery (String query);
|
public abstract IDbDataTable ExecuteQuery(String query);
|
||||||
public abstract int ExecuteNonQuery (String query);
|
public abstract int ExecuteNonQuery(String query);
|
||||||
public abstract int ExecuteInsert (String tableName, List<StringPair> columnNameValues);
|
public abstract int ExecuteInsert(String tableName, List<StringPair> columnNameValues);
|
||||||
public abstract int ExecuteUpdate (String tableName, List<StringPair> columnNameValues, String filter);
|
public abstract int ExecuteUpdate(String tableName, List<StringPair> columnNameValues, String filter);
|
||||||
public abstract int ExecuteDelete (String tableName, String filter);
|
public abstract int ExecuteDelete(String tableName, String filter);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add value pair - used to build value lists for insert and update.
|
/// Add value pair - used to build value lists for insert and update.
|
||||||
/// <para>Caters for delimiting text values and uses 'NULL' for empty text values.</para>
|
/// <para>Caters for delimiting text values and uses 'NULL' for empty text values.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void AddValuePair (List<StringPair> columnNameValues, String columnName, String value, bool delimitString = false)
|
public static void AddValuePair(List<StringPair> columnNameValues, String columnName, String value, bool delimitString = false)
|
||||||
{
|
{
|
||||||
if (delimitString)
|
if (delimitString)
|
||||||
{
|
{
|
||||||
@@ -200,42 +204,42 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
columnNameValues.Add(columnName, value);
|
columnNameValues.Add(columnName, value);
|
||||||
}
|
}
|
||||||
/// <summary>Add SysId value pair - used to build value lists for insert and update.</summary>
|
/// <summary>Add SysId value pair - used to build value lists for insert and update.</summary>
|
||||||
public static void AddValuePair (List<StringPair> columnNameValues, String columnName, SysId value)
|
public static void AddValuePair(List<StringPair> columnNameValues, String columnName, SysId value)
|
||||||
{
|
{
|
||||||
columnNameValues.Add(columnName, SysId.ToInt(value).ToString());
|
columnNameValues.Add(columnName, SysId.ToInt(value).ToString());
|
||||||
}
|
}
|
||||||
/// <summary>Add numeric value pair - used to build value lists for insert and update.</summary>
|
/// <summary>Add numeric value pair - used to build value lists for insert and update.</summary>
|
||||||
public static void AddValuePair (List<StringPair> columnNameValues, String columnName, long value)
|
public static void AddValuePair(List<StringPair> columnNameValues, String columnName, long value)
|
||||||
{
|
{
|
||||||
columnNameValues.Add(columnName, value.ToString());
|
columnNameValues.Add(columnName, value.ToString());
|
||||||
}
|
}
|
||||||
/// <summary>Add decimal value pair - used to build value lists for insert and update.</summary>
|
/// <summary>Add decimal value pair - used to build value lists for insert and update.</summary>
|
||||||
public static void AddValuePair (List<StringPair> columnNameValues, String columnName, decimal value)
|
public static void AddValuePair(List<StringPair> columnNameValues, String columnName, decimal value)
|
||||||
{
|
{
|
||||||
columnNameValues.Add(columnName, value.ToString());
|
columnNameValues.Add(columnName, value.ToString());
|
||||||
}
|
}
|
||||||
/// <summary>Add date/time value pair - used to build value lists for insert and update.</summary>
|
/// <summary>Add date/time value pair - used to build value lists for insert and update.</summary>
|
||||||
public static void AddValuePair (List<StringPair> columnNameValues, String columnName, DateTime value)
|
public static void AddValuePair(List<StringPair> columnNameValues, String columnName, DateTime value)
|
||||||
{
|
{
|
||||||
AddValuePair(columnNameValues, columnName, DateUtil.Format(value, "yyyy/MM/dd HH:mm:ss"), true);
|
AddValuePair(columnNameValues, columnName, DateUtil.Format(value, "yyyy/MM/dd HH:mm:ss"), true);
|
||||||
}
|
}
|
||||||
// Specific queries.
|
// Specific queries.
|
||||||
public abstract long GetRowCount (String tableName, String filter);
|
public abstract long GetRowCount(String tableName, String filter);
|
||||||
public abstract DataValue GetRowValue (String tableName, String columnName, String filter);
|
public abstract DataValue GetRowValue(String tableName, String columnName, String filter);
|
||||||
public abstract DataValue GetRowValue (String tableName, String columnName, String filter, DbGetValueType getValueType);
|
public abstract DataValue GetRowValue(String tableName, String columnName, String filter, DbGetValueType getValueType);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// D a t a b a s e S c h e m a
|
// D a t a b a s e S c h e m a
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public abstract List<String> GetTableNames (bool refresh = false);
|
public abstract List<String> GetTableNames(bool refresh = false);
|
||||||
public abstract List<DbDfnTable> GetTableDfns (bool refresh = false);
|
public abstract List<DbDfnTable> GetTableDfns(bool refresh = false);
|
||||||
public abstract DbDfnTable GetTableDfn (String name, bool refresh = false);
|
public abstract DbDfnTable GetTableDfn(String name, bool refresh = false);
|
||||||
public bool TableExists (String tableName)
|
public bool TableExists(String tableName)
|
||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(tableName)) return false;
|
if (StringUtil.IsEmpty(tableName)) return false;
|
||||||
return GetTableNames().Exists(table => table.EqualsCI(tableName));
|
return GetTableNames().Exists(table => table.EqualsCI(tableName));
|
||||||
}
|
}
|
||||||
public bool ColumnExists (String tableName, String columnName)
|
public bool ColumnExists(String tableName, String columnName)
|
||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(tableName) || StringUtil.IsEmpty(columnName)) return false;
|
if (StringUtil.IsEmpty(tableName) || StringUtil.IsEmpty(columnName)) return false;
|
||||||
DbDfnTable table = GetTableDfn(tableName);
|
DbDfnTable table = GetTableDfn(tableName);
|
||||||
@@ -243,7 +247,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
return table.HasColumnByName(columnName);
|
return table.HasColumnByName(columnName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public bool IndexExists (String tableName, String indexName)
|
public bool IndexExists(String tableName, String indexName)
|
||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(tableName) || StringUtil.IsEmpty(indexName)) return false;
|
if (StringUtil.IsEmpty(tableName) || StringUtil.IsEmpty(indexName)) return false;
|
||||||
DbDfnTable table = GetTableDfn(tableName);
|
DbDfnTable table = GetTableDfn(tableName);
|
||||||
@@ -263,7 +267,7 @@ namespace Sarand.Net.Standard.Dbas.Base
|
|||||||
// Logging.
|
// Logging.
|
||||||
public static SaMessageLevel LoggingLevel { get; set; } = SaMessageLevel.None;
|
public static SaMessageLevel LoggingLevel { get; set; } = SaMessageLevel.None;
|
||||||
public static String LoggingPrefix { get; set; } = " ~~~ ";
|
public static String LoggingPrefix { get; set; } = " ~~~ ";
|
||||||
protected static void Log (String fn, String message, SaMessageLevel level = SaMessageLevel.Debug)
|
protected static void Log(String fn, String message, SaMessageLevel level = SaMessageLevel.Debug)
|
||||||
{
|
{
|
||||||
if ((int)level > (int)LoggingLevel) return;
|
if ((int)level > (int)LoggingLevel) return;
|
||||||
SaLogger.Log((fn + "\n\t" + message).Trim(), level);
|
SaLogger.Log((fn + "\n\t" + message).Trim(), level);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -173,10 +173,9 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
// Query records.
|
// Query records.
|
||||||
public override IDbDataTable ExecuteQuery(String query)
|
public override IDbDataTable ExecuteQuery(String query)
|
||||||
{
|
{
|
||||||
String fn = GetType().Name + ".ExecuteQuery";
|
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
DataTable dataTable = null;
|
DataTable dataTable = null;
|
||||||
Log(fn, "Query: " + query, SaMessageLevel.Debug);
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (DbConnection dbConnection = CreateConnection())
|
using (DbConnection dbConnection = CreateConnection())
|
||||||
@@ -191,7 +190,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
SaLogger.Error(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
||||||
SetErrorState(exc.Message);
|
SetErrorState(exc.Message);
|
||||||
}
|
}
|
||||||
return new DbDataTable(dataTable);
|
return new DbDataTable(dataTable);
|
||||||
@@ -200,9 +199,8 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
/// <summary>Execute a non-query statement and return the row count.</summary>
|
/// <summary>Execute a non-query statement and return the row count.</summary>
|
||||||
public override int ExecuteNonQuery(string query)
|
public override int ExecuteNonQuery(string query)
|
||||||
{
|
{
|
||||||
String fn = GetType().Name + ".ExecuteNonQuery";
|
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
Log(fn, "Query: " + query, SaMessageLevel.Debug);
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
||||||
using (var dbConnection = CreateConnection())
|
using (var dbConnection = CreateConnection())
|
||||||
using (var dbCommand = dbConnection.CreateCommand())
|
using (var dbCommand = dbConnection.CreateCommand())
|
||||||
{
|
{
|
||||||
@@ -215,7 +213,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
SaLogger.Error(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
||||||
SetErrorState(exc.Message);
|
SetErrorState(exc.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,13 +223,12 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
/// <summary>Compile and execute an insert statement and return the row count.</summary>
|
/// <summary>Compile and execute an insert statement and return the row count.</summary>
|
||||||
public override int ExecuteInsert(String tableName, List<StringPair> columnNameValues)
|
public override int ExecuteInsert(String tableName, List<StringPair> columnNameValues)
|
||||||
{
|
{
|
||||||
String fn = GetType().Name + ".ExecuteInsert";
|
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
String query =
|
String query =
|
||||||
"INSERT INTO " + tableName + " " +
|
"INSERT INTO " + tableName + " " +
|
||||||
"(" + columnNameValues.GetValues(StringPair.Value.Value1).Concat(", ") + ") " +
|
"(" + columnNameValues.GetValues(StringPair.Value.Value1).Concat(", ") + ") " +
|
||||||
"VALUES (" + columnNameValues.GetValues(StringPair.Value.Value2).Concat(", ") + ")";
|
"VALUES (" + columnNameValues.GetValues(StringPair.Value.Value2).Concat(", ") + ")";
|
||||||
Log(fn, "Query: " + query, SaMessageLevel.Debug);
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
||||||
using (var dbConnection = CreateConnection())
|
using (var dbConnection = CreateConnection())
|
||||||
using (var dbCommand = dbConnection.CreateCommand())
|
using (var dbCommand = dbConnection.CreateCommand())
|
||||||
{
|
{
|
||||||
@@ -244,7 +241,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
SaLogger.Error(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
||||||
SetErrorState(exc.Message);
|
SetErrorState(exc.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,14 +251,13 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
/// <summary>Compile and execute an update statement and return the row count.</summary>
|
/// <summary>Compile and execute an update statement and return the row count.</summary>
|
||||||
public override int ExecuteUpdate(String tableName, List<StringPair> columnNameValues, String filter)
|
public override int ExecuteUpdate(String tableName, List<StringPair> columnNameValues, String filter)
|
||||||
{
|
{
|
||||||
String fn = GetType().Name + ".ExecuteUpdate";
|
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
String query =
|
String query =
|
||||||
"UPDATE " + tableName + " " +
|
"UPDATE " + tableName + " " +
|
||||||
"SET " + columnNameValues.Concat("=").Concat(", ");
|
"SET " + columnNameValues.Concat("=").Concat(", ");
|
||||||
if (!StringUtil.IsEmpty(filter))
|
if (!StringUtil.IsEmpty(filter))
|
||||||
query += (String)" WHERE " + filter;
|
query += (String)" WHERE " + filter;
|
||||||
Log(fn, "Query: " + query, SaMessageLevel.Debug);
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
||||||
using (var dbConnection = CreateConnection())
|
using (var dbConnection = CreateConnection())
|
||||||
using (var dbCommand = dbConnection.CreateCommand())
|
using (var dbCommand = dbConnection.CreateCommand())
|
||||||
{
|
{
|
||||||
@@ -274,7 +270,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
SaLogger.Error(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
||||||
SetErrorState(exc.Message);
|
SetErrorState(exc.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,12 +280,11 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
/// <summary>Compile and execute a delete statement and return the row count.</summary>
|
/// <summary>Compile and execute a delete statement and return the row count.</summary>
|
||||||
public override int ExecuteDelete(String tableName, String filter)
|
public override int ExecuteDelete(String tableName, String filter)
|
||||||
{
|
{
|
||||||
String fn = GetType().Name + ".ExecuteDelete";
|
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
String query = "DELETE FROM " + tableName;
|
String query = "DELETE FROM " + tableName;
|
||||||
if (!StringUtil.IsEmpty(filter))
|
if (!StringUtil.IsEmpty(filter))
|
||||||
query += " WHERE " + filter;
|
query += " WHERE " + filter;
|
||||||
Log(fn, "Query: " + query, SaMessageLevel.Debug);
|
Log(SysUtil.Fn, "Query: " + query, SaMessageLevel.Debug);
|
||||||
using (var dbConnection = CreateConnection())
|
using (var dbConnection = CreateConnection())
|
||||||
using (var dbCommand = dbConnection.CreateCommand())
|
using (var dbCommand = dbConnection.CreateCommand())
|
||||||
{
|
{
|
||||||
@@ -302,7 +297,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
SaLogger.Error(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc) + "\n\tQuery: " + query, true);
|
||||||
SetErrorState(exc.Message);
|
SetErrorState(exc.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,8 +444,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
{
|
{
|
||||||
if (StringUtil.IsEmpty(tableNameRestriction) && tables.Count > 0) return;
|
if (StringUtil.IsEmpty(tableNameRestriction) && tables.Count > 0) return;
|
||||||
if (!StringUtil.IsEmpty(tableNameRestriction) && tables.Exists(item => item.Name.Equals(tableNameRestriction))) return;
|
if (!StringUtil.IsEmpty(tableNameRestriction) && tables.Exists(item => item.Name.Equals(tableNameRestriction))) return;
|
||||||
String fn = GetType().Name + ".PopulateTableNames";
|
if (SacsSystem.DebugMode) SaLogger.Debug(SysUtil.Fn + (!StringUtil.IsEmpty(tableNameRestriction) ? " Table: " + tableNameRestriction : " "));
|
||||||
if (SacsSystem.DebugMode) SaLogger.Debug(fn + (!StringUtil.IsEmpty(tableNameRestriction) ? " Table: " + tableNameRestriction : " "));
|
|
||||||
String[] restrictions = new String[] { null, null, tableNameRestriction }; // database, owner, table name, type
|
String[] restrictions = new String[] { null, null, tableNameRestriction }; // database, owner, table name, type
|
||||||
using (DataTable tableSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Tables, restrictions))
|
using (DataTable tableSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Tables, restrictions))
|
||||||
{
|
{
|
||||||
@@ -490,7 +484,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
else if (colName.EqualsCI("REMARKS"))
|
else if (colName.EqualsCI("REMARKS"))
|
||||||
remarks = value;
|
remarks = value;
|
||||||
else
|
else
|
||||||
SaLogger.Warn(fn + " Unrecognised column name: '" + colName + "'");
|
SaLogger.Warn(SysUtil.Fn + " Unrecognised column name: '" + colName + "'");
|
||||||
}
|
}
|
||||||
// TODO Why is Type sometimes "BASE TABLE"?
|
// TODO Why is Type sometimes "BASE TABLE"?
|
||||||
if (!StringUtil.IsEmpty(tableName) && (type.EqualsCI("Table") || type.EqualsCI("Base Table")) && (!schema.EqualsCI("sys") || !tableName.Left(9).EqualsCI("trace_xe_")))
|
if (!StringUtil.IsEmpty(tableName) && (type.EqualsCI("Table") || type.EqualsCI("Base Table")) && (!schema.EqualsCI("sys") || !tableName.Left(9).EqualsCI("trace_xe_")))
|
||||||
@@ -513,8 +507,7 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
private void PopulateTableColumns(DbConnection dbConnection, DbDfnTable table)
|
private void PopulateTableColumns(DbConnection dbConnection, DbDfnTable table)
|
||||||
{
|
{
|
||||||
String fn = GetType().Name + ".PopulateTableColumns";
|
if (SacsSystem.DebugMode) SaLogger.Debug(SysUtil.Fn + " Table: " + table.Name);
|
||||||
if (SacsSystem.DebugMode) SaLogger.Debug(fn + " Table: " + table.Name);
|
|
||||||
short columnPos = 0;
|
short columnPos = 0;
|
||||||
String[] restrictions = new String[] { null, table.Schema, table.Name, null }; // database, owner, table name, column name
|
String[] restrictions = new String[] { null, table.Schema, table.Name, null }; // database, owner, table name, column name
|
||||||
using (DataTable columnSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Columns, restrictions))
|
using (DataTable columnSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Columns, restrictions))
|
||||||
@@ -718,7 +711,6 @@ namespace Sarand.Net.Standard.Dbas.Data
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
private void PopulateTableIndices(DbConnection dbConnection, DbDfnTable table)
|
private void PopulateTableIndices(DbConnection dbConnection, DbDfnTable table)
|
||||||
{
|
{
|
||||||
String fn = GetType().Name + ".PopulateTableIndices";
|
|
||||||
String[] restrictions = new String[] { null, table.Schema, table.Name }; // database, owner, table name
|
String[] restrictions = new String[] { null, table.Schema, table.Name }; // database, owner, table name
|
||||||
using (DataTable columnSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Indexes, restrictions))
|
using (DataTable columnSchema = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Indexes, restrictions))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -41,10 +41,6 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Definitions.
|
// Definitions.
|
||||||
public interface IProcessNotifier : ISacsProcessNotifier
|
|
||||||
{
|
|
||||||
void OnSchemaComparisonItemAdded(SaDbProcess_CompareDatabaseSchemas proc);
|
|
||||||
}
|
|
||||||
public class SchemaComparisonItem
|
public class SchemaComparisonItem
|
||||||
{
|
{
|
||||||
internal SchemaComparisonItem(String tableName, String columnName, int columnPosition, String indexName, String comment)
|
internal SchemaComparisonItem(String tableName, String columnName, int columnPosition, String indexName, String comment)
|
||||||
@@ -68,7 +64,6 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
private Config config;
|
private Config config;
|
||||||
private IProcessNotifier processNotifier = null;
|
|
||||||
private readonly List<SchemaComparisonItem> schemaComparisonItems = new List<SchemaComparisonItem>();
|
private readonly List<SchemaComparisonItem> schemaComparisonItems = new List<SchemaComparisonItem>();
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
@@ -88,13 +83,19 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Properties.
|
// Properties.
|
||||||
public override string ProcessDescription { get; } = "Database Schema Comparison";
|
public override string ProcessDescription { get; } = "Database Schema Comparison";
|
||||||
public new IProcessNotifier ProcessNotifier
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Events.
|
||||||
|
|
||||||
|
// Processing Completed.
|
||||||
|
public class SchemaComparisonItemAddedEventArgs : EventArgs { }
|
||||||
|
public event EventHandler<SchemaComparisonItemAddedEventArgs> OnSchemaComparisonItemAdded;
|
||||||
|
protected virtual void InvokeSchemaComparisonItemAdded()
|
||||||
{
|
{
|
||||||
get { return processNotifier; }
|
if (OnSchemaComparisonItemAdded != null)
|
||||||
set
|
|
||||||
{
|
{
|
||||||
processNotifier = value;
|
SchemaComparisonItemAddedEventArgs args = new SchemaComparisonItemAddedEventArgs();
|
||||||
base.ProcessNotifier = value;
|
OnSchemaComparisonItemAdded(this, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +113,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
protected override bool Run()
|
protected override bool Run()
|
||||||
{
|
{
|
||||||
schemaComparisonItems.Clear();
|
schemaComparisonItems.Clear();
|
||||||
if (config.SourceDatabase == null && config.SourceTables == null) return SetProcessError("Source database must be supplied.");
|
if (config.SourceDatabase == null && config.SourceTables == null) return AddErrorMessage("Source database must be supplied.");
|
||||||
|
|
||||||
CompareTables();
|
CompareTables();
|
||||||
return OK;
|
return OK;
|
||||||
@@ -393,7 +394,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
private void AddSchemaComparisonItem(String tableName, String columnName, int position, String indexName, String comment)
|
private void AddSchemaComparisonItem(String tableName, String columnName, int position, String indexName, String comment)
|
||||||
{
|
{
|
||||||
schemaComparisonItems.Add(new SchemaComparisonItem(tableName, columnName, position, indexName, comment));
|
schemaComparisonItems.Add(new SchemaComparisonItem(tableName, columnName, position, indexName, comment));
|
||||||
if (ProcessNotifier != null) ProcessNotifier.OnSchemaComparisonItemAdded(this);
|
InvokeSchemaComparisonItemAdded();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
}
|
}
|
||||||
public new class Config : SaProcess_Base.Config
|
public new class Config : SaProcess_Base.Config
|
||||||
{
|
{
|
||||||
public Config ()
|
public Config()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public SourceDefinitionType SourceDefinitionType { get; set; }
|
public SourceDefinitionType SourceDefinitionType { get; set; }
|
||||||
@@ -43,9 +43,6 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Definitions.
|
// Definitions.
|
||||||
public interface IProcessNotifier : ISacsProcessNotifier
|
|
||||||
{
|
|
||||||
}
|
|
||||||
private class Statistics
|
private class Statistics
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -53,17 +50,16 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
private Config config;
|
private Config config;
|
||||||
private IProcessNotifier processNotifier;
|
|
||||||
private readonly List<DbDfnTable> tableDfns = new List<DbDfnTable>();
|
private readonly List<DbDfnTable> tableDfns = new List<DbDfnTable>();
|
||||||
private Statistics stats;
|
private Statistics stats;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Construction.
|
// Construction.
|
||||||
public SaDbProcess_ConvertDbDefinition (Config config) : base(config)
|
public SaDbProcess_ConvertDbDefinition(Config config) : base(config)
|
||||||
{
|
{
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
protected override void Dispose (bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
@@ -74,15 +70,6 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Properties.
|
// Properties.
|
||||||
public override string ProcessDescription { get; } = "Database Definition Convertor";
|
public override string ProcessDescription { get; } = "Database Definition Convertor";
|
||||||
public new IProcessNotifier ProcessNotifier
|
|
||||||
{
|
|
||||||
get { return processNotifier; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
processNotifier = value;
|
|
||||||
base.ProcessNotifier = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>Processing statistics.</summary>
|
/// <summary>Processing statistics.</summary>
|
||||||
public override List<StringPair> ProcessingStatistics
|
public override List<StringPair> ProcessingStatistics
|
||||||
{
|
{
|
||||||
@@ -102,7 +89,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// P r o c e s s i n g
|
// P r o c e s s i n g
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
protected override bool Run ()
|
protected override bool Run()
|
||||||
{
|
{
|
||||||
// Initialise process.
|
// Initialise process.
|
||||||
tableDfns.Clear();
|
tableDfns.Clear();
|
||||||
@@ -115,32 +102,32 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
protected bool ValidateConfiguration ()
|
protected bool ValidateConfiguration()
|
||||||
{
|
{
|
||||||
// Source file.
|
// Source file.
|
||||||
if (config.SourceDefinitionType <= 0)
|
if (config.SourceDefinitionType <= 0)
|
||||||
return SetProcessError("Source definition type must be specified.");
|
return AddErrorMessage("Source definition type must be specified.");
|
||||||
if (StringUtil.IsEmpty(config.SourceDefinitionFilePath))
|
if (StringUtil.IsEmpty(config.SourceDefinitionFilePath))
|
||||||
return SetProcessError("Source definition file must be specified.");
|
return AddErrorMessage("Source definition file must be specified.");
|
||||||
if (!FileUtil.IsFile(config.SourceDefinitionFilePath))
|
if (!FileUtil.IsFile(config.SourceDefinitionFilePath))
|
||||||
return SetProcessError("Source definition file not found.");
|
return AddErrorMessage("Source definition file not found.");
|
||||||
|
|
||||||
// Target file.
|
// Target file.
|
||||||
if (config.TargetDefinitionType <= 0)
|
if (config.TargetDefinitionType <= 0)
|
||||||
return SetProcessError("Target definition type must be specified.");
|
return AddErrorMessage("Target definition type must be specified.");
|
||||||
if (StringUtil.IsEmpty(config.TargetDefinitionFilePath))
|
if (StringUtil.IsEmpty(config.TargetDefinitionFilePath))
|
||||||
return SetProcessError("Target definition file must be specified.");
|
return AddErrorMessage("Target definition file must be specified.");
|
||||||
if (!DirectoryUtil.DirectoryExists(DirectoryUtil.GetDirectoryName(config.TargetDefinitionFilePath)))
|
if (!DirectoryUtil.DirectoryExists(DirectoryUtil.GetDirectoryName(config.TargetDefinitionFilePath)))
|
||||||
return SetProcessError("Target folder not found.");
|
return AddErrorMessage("Target folder not found.");
|
||||||
|
|
||||||
if (config.SourceDefinitionFilePath.EqualsCI(config.TargetDefinitionFilePath))
|
if (config.SourceDefinitionFilePath.EqualsCI(config.TargetDefinitionFilePath))
|
||||||
return SetProcessError("Target file must not be the same as the source file.");
|
return AddErrorMessage("Target file must not be the same as the source file.");
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
private bool ConvertCppDatabaseDefinition ()
|
private bool ConvertCppDatabaseDefinition()
|
||||||
{
|
{
|
||||||
if (!OK) return false;
|
if (!OK) return false;
|
||||||
|
|
||||||
@@ -169,7 +156,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
}
|
}
|
||||||
private class SourceDefinition_Params
|
private class SourceDefinition_Params
|
||||||
{
|
{
|
||||||
protected SourceDefinition_Params () { }
|
protected SourceDefinition_Params() { }
|
||||||
public int LineNumber { get; set; } = -1;
|
public int LineNumber { get; set; } = -1;
|
||||||
public int TableIdx { get; set; } = -1;
|
public int TableIdx { get; set; } = -1;
|
||||||
public int ColumnIdx { get; set; } = -1;
|
public int ColumnIdx { get; set; } = -1;
|
||||||
@@ -186,7 +173,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
public Dictionary<StringPair, ColumnData> ColumnMap { get; } = new Dictionary<StringPair, ColumnData>();
|
public Dictionary<StringPair, ColumnData> ColumnMap { get; } = new Dictionary<StringPair, ColumnData>();
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
private bool ExtractDatabaseDefinition ()
|
private bool ExtractDatabaseDefinition()
|
||||||
{
|
{
|
||||||
if (!OK) return false;
|
if (!OK) return false;
|
||||||
|
|
||||||
@@ -245,7 +232,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
file.Close();
|
file.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exc) { SaLogger.Warn(ExceptionUtil.GetLogMessage(exc)); SetProcessError(ExceptionUtil.GetErrorStateMessage(exc)); }
|
catch (Exception exc) { SaLogger.Warn(ExceptionUtil.GetLogMessage(exc)); AddErrorMessage(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -253,7 +240,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// C + + C o d e S o u r c e
|
// C + + C o d e S o u r c e
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
private readonly Dictionary<int,String> cppColumnDataTypes = new Dictionary<int, string>()
|
private readonly Dictionary<int, String> cppColumnDataTypes = new Dictionary<int, string>()
|
||||||
{
|
{
|
||||||
{ 1, "VarChar" },
|
{ 1, "VarChar" },
|
||||||
{ -7, "Bit" },
|
{ -7, "Bit" },
|
||||||
@@ -265,7 +252,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
{ 8, "Double" },
|
{ 8, "Double" },
|
||||||
{ 93, "DateTime" }
|
{ 93, "DateTime" }
|
||||||
};
|
};
|
||||||
private bool ExtractDatabaseDefinitionLine_CppCode (SourceDefinition_Params_CppCode sourceDfnParams, String line)
|
private bool ExtractDatabaseDefinitionLine_CppCode(SourceDefinition_Params_CppCode sourceDfnParams, String line)
|
||||||
{
|
{
|
||||||
if (!OK) return false;
|
if (!OK) return false;
|
||||||
|
|
||||||
@@ -276,7 +263,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
{
|
{
|
||||||
// Table enum start.
|
// Table enum start.
|
||||||
if (sourceDfnParams.TablesEnumFound)
|
if (sourceDfnParams.TablesEnumFound)
|
||||||
return SetProcessError("Found multiple table enums at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
return AddErrorMessage("Found multiple table enums at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
sourceDfnParams.TablesEnumFound = true;
|
sourceDfnParams.TablesEnumFound = true;
|
||||||
sourceDfnParams.InTablesEnum = true;
|
sourceDfnParams.InTablesEnum = true;
|
||||||
return OK;
|
return OK;
|
||||||
@@ -289,13 +276,13 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
else if (!line.ContainsCI("eSaDbTblUnknown"))
|
else if (!line.ContainsCI("eSaDbTblUnknown"))
|
||||||
{
|
{
|
||||||
if (!line.ContainsCI("eSaDbTbl"))
|
if (!line.ContainsCI("eSaDbTbl"))
|
||||||
return SetProcessError("Invalid table definition on line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
return AddErrorMessage("Invalid table definition on line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
// Extract table name.
|
// Extract table name.
|
||||||
String tableName = line.ReplaceAll("eSaDbTbl","").ReplaceAll(",","");
|
String tableName = line.ReplaceAll("eSaDbTbl", "").ReplaceAll(",", "");
|
||||||
if (StringUtil.IsEmpty(tableName))
|
if (StringUtil.IsEmpty(tableName))
|
||||||
return SetProcessError("Blank table name on line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
return AddErrorMessage("Blank table name on line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
if (tableDfns.Exists(item => item.Name.EqualsCI(tableName)))
|
if (tableDfns.Exists(item => item.Name.EqualsCI(tableName)))
|
||||||
return SetProcessError("Duplicate table name on line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
return AddErrorMessage("Duplicate table name on line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
// Add this table to the list.
|
// Add this table to the list.
|
||||||
sourceDfnParams.TableIdx++;
|
sourceDfnParams.TableIdx++;
|
||||||
//SaLogger.Debug("Table #" + sourceDfnParams.TableIdx + ": " + tableName);
|
//SaLogger.Debug("Table #" + sourceDfnParams.TableIdx + ": " + tableName);
|
||||||
@@ -310,7 +297,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
{
|
{
|
||||||
// Column enum start.
|
// Column enum start.
|
||||||
if (sourceDfnParams.ColumnsEnumFound)
|
if (sourceDfnParams.ColumnsEnumFound)
|
||||||
return SetProcessError("Found multiple columns enums at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
return AddErrorMessage("Found multiple columns enums at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
sourceDfnParams.ColumnsEnumFound = true;
|
sourceDfnParams.ColumnsEnumFound = true;
|
||||||
sourceDfnParams.InColumnsEnum = true;
|
sourceDfnParams.InColumnsEnum = true;
|
||||||
return OK;
|
return OK;
|
||||||
@@ -323,7 +310,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
else if (!line.ContainsCI("eSaDbColUnknown"))
|
else if (!line.ContainsCI("eSaDbColUnknown"))
|
||||||
{
|
{
|
||||||
if (!line.ContainsCI("eSaDbCol"))
|
if (!line.ContainsCI("eSaDbCol"))
|
||||||
return SetProcessError("Invalid column definition on line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
return AddErrorMessage("Invalid column definition on line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
// Column definitions:
|
// Column definitions:
|
||||||
// eSaDbColUnknown = -1,
|
// eSaDbColUnknown = -1,
|
||||||
// #define eSaDbColVendorType_ListID (eSaDbColumn)4101
|
// #define eSaDbColVendorType_ListID (eSaDbColumn)4101
|
||||||
@@ -345,7 +332,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
// Split table and column names on Underscore.
|
// Split table and column names on Underscore.
|
||||||
String[] tableColumnNameParts = tableColumnName.Split('_');
|
String[] tableColumnNameParts = tableColumnName.Split('_');
|
||||||
if (tableColumnNameParts.Length != 2)
|
if (tableColumnNameParts.Length != 2)
|
||||||
return SetProcessError("Invalid column definition on line (missing underscore?) " + sourceDfnParams.LineNumber + ": " + line + ".");
|
return AddErrorMessage("Invalid column definition on line (missing underscore?) " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
sourceDfnParams.ColumnIdx++;
|
sourceDfnParams.ColumnIdx++;
|
||||||
String tableName = tableColumnNameParts[0];
|
String tableName = tableColumnNameParts[0];
|
||||||
String columnName = tableColumnNameParts[1];
|
String columnName = tableColumnNameParts[1];
|
||||||
@@ -360,7 +347,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
{
|
{
|
||||||
// Column definitions start.
|
// Column definitions start.
|
||||||
if (sourceDfnParams.ColumnsDfnsFound)
|
if (sourceDfnParams.ColumnsDfnsFound)
|
||||||
return SetProcessError("Found multiple column definitions at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
return AddErrorMessage("Found multiple column definitions at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
sourceDfnParams.ColumnsDfnsFound = true;
|
sourceDfnParams.ColumnsDfnsFound = true;
|
||||||
sourceDfnParams.InColumnsDfns = true;
|
sourceDfnParams.InColumnsDfns = true;
|
||||||
sourceDfnParams.ColumnIdx = -1;
|
sourceDfnParams.ColumnIdx = -1;
|
||||||
@@ -388,40 +375,40 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
// eTime = 93 SQL_C_TYPE_TIMESTAMP
|
// eTime = 93 SQL_C_TYPE_TIMESTAMP
|
||||||
foreach (String columnDfnDataRaw in line.Split(new String[] { "}," }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (String columnDfnDataRaw in line.Split(new String[] { "}," }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
String columnDfnData = columnDfnDataRaw.ReplaceAll("{","").TrimAll();
|
String columnDfnData = columnDfnDataRaw.ReplaceAll("{", "").TrimAll();
|
||||||
//SaLogger.Debug("Column dfn: " + columnDfnData);
|
//SaLogger.Debug("Column dfn: " + columnDfnData);
|
||||||
String[] columnDfnParts = columnDfnData.Split(',');
|
String[] columnDfnParts = columnDfnData.Split(',');
|
||||||
if (columnDfnParts.Length != 4) return SetProcessError("Invalid column definition (expecting 4 parts) at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (columnDfnParts.Length != 4) return AddErrorMessage("Invalid column definition (expecting 4 parts) at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
String tableIdxRaw = columnDfnParts[0].TrimAll();
|
String tableIdxRaw = columnDfnParts[0].TrimAll();
|
||||||
int tableIdx = StringUtil.ToInt(tableIdxRaw);
|
int tableIdx = StringUtil.ToInt(tableIdxRaw);
|
||||||
String columnName = columnDfnParts[1].TrimAll().ReplaceAll("\"","");
|
String columnName = columnDfnParts[1].TrimAll().ReplaceAll("\"", "");
|
||||||
String dataTypeRaw = columnDfnParts[2].TrimAll();
|
String dataTypeRaw = columnDfnParts[2].TrimAll();
|
||||||
int dataType = StringUtil.ToInt(dataTypeRaw);
|
int dataType = StringUtil.ToInt(dataTypeRaw);
|
||||||
String columnLengthRaw = columnDfnParts[3].TrimAll();
|
String columnLengthRaw = columnDfnParts[3].TrimAll();
|
||||||
int columnLength = StringUtil.ToInt(columnLengthRaw);
|
int columnLength = StringUtil.ToInt(columnLengthRaw);
|
||||||
if (!tableIdxRaw.IsNumeric()) return SetProcessError("Invalid table index in column definition (" + tableIdxRaw + ") at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (!tableIdxRaw.IsNumeric()) return AddErrorMessage("Invalid table index in column definition (" + tableIdxRaw + ") at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
if (StringUtil.IsEmpty(columnName)) return SetProcessError("Blank name in column definition at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (StringUtil.IsEmpty(columnName)) return AddErrorMessage("Blank name in column definition at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
if (!dataTypeRaw.IsNumeric(true) || !cppColumnDataTypes.ContainsKey(dataType)) return SetProcessError("Invalid data type in column definition (" + dataTypeRaw + ") at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (!dataTypeRaw.IsNumeric(true) || !cppColumnDataTypes.ContainsKey(dataType)) return AddErrorMessage("Invalid data type in column definition (" + dataTypeRaw + ") at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
if (!columnLengthRaw.IsNumeric()) return SetProcessError("Invalid column length in column definition (" + columnLengthRaw + ") at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (!columnLengthRaw.IsNumeric()) return AddErrorMessage("Invalid column length in column definition (" + columnLengthRaw + ") at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
// Table definition.
|
// Table definition.
|
||||||
String tableName = sourceDfnParams.TableMap.Values.ToList().Find(item => item.TableIdx == tableIdx)?.TableName ?? "";
|
String tableName = sourceDfnParams.TableMap.Values.ToList().Find(item => item.TableIdx == tableIdx)?.TableName ?? "";
|
||||||
if (StringUtil.IsEmpty(tableName)) return SetProcessError("Unable to identify table name for Table idx " + tableIdx + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (StringUtil.IsEmpty(tableName)) return AddErrorMessage("Unable to identify table name for Table idx " + tableIdx + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
DbDfnTable tableDfn = tableDfns.GetTableByName(tableName);
|
DbDfnTable tableDfn = tableDfns.GetTableByName(tableName);
|
||||||
if (tableDfn == null) return SetProcessError("Unable to retrieve table definition for Table name " + tableName + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (tableDfn == null) return AddErrorMessage("Unable to retrieve table definition for Table name " + tableName + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
// Column data.
|
// Column data.
|
||||||
sourceDfnParams.ColumnIdx++;
|
sourceDfnParams.ColumnIdx++;
|
||||||
ColumnData columnData = sourceDfnParams.ColumnMap.Values.ToList().Find(item => item.TableName.EqualsCI(tableName) && item.ColumnIdx == sourceDfnParams.ColumnIdx);
|
ColumnData columnData = sourceDfnParams.ColumnMap.Values.ToList().Find(item => item.TableName.EqualsCI(tableName) && item.ColumnIdx == sourceDfnParams.ColumnIdx);
|
||||||
if (columnData == null) return SetProcessError("Unable to column data for table " + tableName + " and column " + columnName + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (columnData == null) return AddErrorMessage("Unable to column data for table " + tableName + " and column " + columnName + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
if (columnData.ColumnName.EqualsCI(columnName)) return SetProcessError("Inconsistent column name for table " + tableName + " and column " + columnName + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (columnData.ColumnName.EqualsCI(columnName)) return AddErrorMessage("Inconsistent column name for table " + tableName + " and column " + columnName + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
// Column definition.
|
// Column definition.
|
||||||
DbDfnColumn columnDfn = new DbDfnColumn()
|
DbDfnColumn columnDfn = new DbDfnColumn()
|
||||||
{
|
{
|
||||||
Table = tableName,
|
Table = tableName,
|
||||||
Name = columnName,
|
Name = columnName,
|
||||||
DataType = EnumUtil.ParseEnum(cppColumnDataTypes.GetValue(dataType,""),DbColumnDataType.Unknown),
|
DataType = EnumUtil.ParseEnum(cppColumnDataTypes.GetValue(dataType, ""), DbColumnDataType.Unknown),
|
||||||
Size = columnLength
|
Size = columnLength
|
||||||
};
|
};
|
||||||
if (columnDfn.DataType < 0) return SetProcessError("Invalid data type for table " + tableName + " and column " + columnName + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
if (columnDfn.DataType < 0) return AddErrorMessage("Invalid data type for table " + tableName + " and column " + columnName + " at line " + sourceDfnParams.LineNumber + ": " + line + ".");
|
||||||
tableDfn.AddColumn(columnDfn);
|
tableDfn.AddColumn(columnDfn);
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public List<DbDfnTable> ConvertXmlToTables(String xmlSchemaData)
|
public List<DbDfnTable> ConvertXmlToTables(String xmlSchemaData)
|
||||||
{
|
{
|
||||||
ClearProcessError();
|
ClearProcessMessages();
|
||||||
String fn = GetType().Name + ".ConvertXmlToTables";
|
String fn = GetType().Name + ".ConvertXmlToTables";
|
||||||
Dictionary<String, DbDfnTable> tables = new Dictionary<String, DbDfnTable>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<String, DbDfnTable> tables = new Dictionary<String, DbDfnTable>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ namespace Sarand.Net.Standard.Dbas.Proc
|
|||||||
}
|
}
|
||||||
catch (Exception exc)
|
catch (Exception exc)
|
||||||
{
|
{
|
||||||
SetProcessError(exc.GetErrorStateMessage());
|
AddErrorMessage(exc.GetErrorStateMessage());
|
||||||
SaLogger.Warn(fn + " " + ExceptionUtil.GetLogMessage(exc));
|
SaLogger.Warn(fn + " " + ExceptionUtil.GetLogMessage(exc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using Sarand.Net.Standard.Dbas.Data;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.Odbc;
|
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Sarand.Net.Standard.Base.Dbas;
|
using Sarand.Net.Standard.Base.Dbas;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.2" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.2" />
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Data.Odbc" Version="5.0.0" />
|
<PackageReference Include="System.Data.Odbc" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ namespace Sarand.Net.Standard.Mobile.Forms.Templates
|
|||||||
{
|
{
|
||||||
base.OnRemoved(view);
|
base.OnRemoved(view);
|
||||||
}
|
}
|
||||||
|
[Obsolete("OnChildRemoved(Element) is obsolete as of version 4.8.0. Please use OnChildRemoved(Element, int) instead.")]
|
||||||
protected override void OnChildRemoved (Element child)
|
protected override void OnChildRemoved (Element child)
|
||||||
{
|
{
|
||||||
base.OnChildRemoved(child);
|
base.OnChildRemoved(child);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ namespace Sarand.Net.Standard.Mobile.Forms.Panels
|
|||||||
{
|
{
|
||||||
base.OnChildAdded(child);
|
base.OnChildAdded(child);
|
||||||
}
|
}
|
||||||
|
[Obsolete("OnChildRemoved(Element) is obsolete as of version 4.8.0. Please use OnChildRemoved(Element, int) instead.")]
|
||||||
protected override void OnChildRemoved (Element child)
|
protected override void OnChildRemoved (Element child)
|
||||||
{
|
{
|
||||||
base.OnChildRemoved(child);
|
base.OnChildRemoved(child);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
<PackageReference Include="Xamarin.Essentials" Version="1.8.1" />
|
||||||
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2012" />
|
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2622" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Sarand.Net.Standard.Proc.Excel
|
||||||
|
{
|
||||||
|
//=======================================================================
|
||||||
|
public static class ExcelHelper
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Validate worksheet name.
|
||||||
|
/// <para>Worksheet names cannot:</para>
|
||||||
|
/// <para>- Be blank.</para>
|
||||||
|
/// <para>- Contain more than 31 characters.</para>
|
||||||
|
/// <para>- Contain any of the following characters: / \ ? * : [ ]</para>
|
||||||
|
/// <para>- For example, 02/17/2016 would not be a valid worksheet name, but 02-17-2016 would work fine.</para>
|
||||||
|
/// <para>- Begin or end with an apostrophe ('), but they can be used in between text or numbers in a name.</para>
|
||||||
|
/// <para>- Be named "History". This is a reserved word Excel uses internally.</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsValidSheetName(String name)
|
||||||
|
{
|
||||||
|
if (Base.Utils.StringUtil.IsBlank(name)) return false;
|
||||||
|
if (name.Length > 31) return false;
|
||||||
|
if (Regex.IsMatch(name, "[/\\\\?*:[\\]]")) return false;
|
||||||
|
if (name.StartsWith("'") || name.EndsWith("'")) return false;
|
||||||
|
if (name.EqualsCI("History")) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
//=======================================================================
|
||||||
|
}
|
||||||
@@ -140,7 +140,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
Yellow = 6,
|
Yellow = 6,
|
||||||
Pink = 7,
|
Pink = 7,
|
||||||
Magenta = 7,
|
Magenta = 7,
|
||||||
Turqoise = 8,
|
Turquoise = 8,
|
||||||
Cyan = 8,
|
Cyan = 8,
|
||||||
DarkRed = 9,
|
DarkRed = 9,
|
||||||
Green = 10,
|
Green = 10,
|
||||||
@@ -151,7 +151,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
Gray25 = 15,
|
Gray25 = 15,
|
||||||
Gray50 = 16,
|
Gray50 = 16,
|
||||||
SkyBlue = 33,
|
SkyBlue = 33,
|
||||||
LightTurqoise = 34,
|
LightTurquoise = 34,
|
||||||
LightGreen = 35,
|
LightGreen = 35,
|
||||||
LightYellow = 36,
|
LightYellow = 36,
|
||||||
PaleBlue = 37,
|
PaleBlue = 37,
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ using Sarand.Net.Standard.Base.Core;
|
|||||||
using Sarand.Net.Standard.Base.Bus;
|
using Sarand.Net.Standard.Base.Bus;
|
||||||
using Sarand.Net.Standard.Base.App;
|
using Sarand.Net.Standard.Base.App;
|
||||||
using Sarand.Net.Standard.Base.Utils;
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
using NPOI.SS.UserModel;
|
||||||
|
using NPOI.SS.Formula.Functions;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Sarand.Net.Standard.Proc.Excel
|
namespace Sarand.Net.Standard.Proc.Excel
|
||||||
{
|
{
|
||||||
@@ -16,24 +20,24 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
//=======================================================================
|
//=======================================================================
|
||||||
public class SaMsExcelRange
|
public class SaMsExcelRange
|
||||||
{
|
{
|
||||||
public uint ColFrom { get; set; } = 0;
|
public uint ColFromPos { get; set; } = 0;
|
||||||
public uint ColTo { get; set; } = 0;
|
public uint ColToPos { get; set; } = 0;
|
||||||
public uint RowFrom { get; set; } = 0;
|
public uint RowFromPos { get; set; } = 0;
|
||||||
public uint RowTo { get; set; } = 0;
|
public uint RowToPos { get; set; } = 0;
|
||||||
public SaMsExcelRange() { }
|
public SaMsExcelRange() { }
|
||||||
public SaMsExcelRange(uint colPos, uint rowPos)
|
public SaMsExcelRange(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
ColFrom = colPos;
|
ColFromPos = colPos;
|
||||||
ColTo = colPos;
|
ColToPos = colPos;
|
||||||
RowFrom = rowPos;
|
RowFromPos = rowPos;
|
||||||
RowTo = rowPos;
|
RowToPos = rowPos;
|
||||||
}
|
}
|
||||||
public SaMsExcelRange(uint colPosFrom, uint rowPosFrom, uint colPosTo, uint rowPosTo)
|
public SaMsExcelRange(uint colPosFrom, uint rowPosFrom, uint colPosTo, uint rowPosTo)
|
||||||
{
|
{
|
||||||
ColFrom = colPosFrom;
|
ColFromPos = colPosFrom;
|
||||||
ColTo = colPosTo;
|
ColToPos = colPosTo;
|
||||||
RowFrom = rowPosFrom;
|
RowFromPos = rowPosFrom;
|
||||||
RowTo = rowPosTo;
|
RowToPos = rowPosTo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
@@ -78,17 +82,29 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
//=======================================================================
|
//=======================================================================
|
||||||
public class SaMsExcelColumnHeading_Config
|
public class SaMsExcelColumnHeading_Config
|
||||||
{
|
{
|
||||||
public double ColumnWidthPixelsPerCm { get; set; } = 43.0; // Between 10 and 100
|
// Heading configuration.
|
||||||
public uint FirstHeadingRow { get; set; } = 1; // Must be > 0
|
/// <summary>Pixels per cm. Default 43. Min 10, max 100.</summary>
|
||||||
public uint FirstHeadingColumn { get; set; } = 1; // Must be > 0
|
public double ColumnWidthPixelsPerCm { get; set; } = 43.0;
|
||||||
public uint FreezeColumn { get; set; } = 0; // 0 = don't freeze
|
/// <summary>First heading column position (from 1). Default 1. Must be > 0.</summary>
|
||||||
public short HeadingFontSize { get; set; } = 9;
|
public uint FirstHeadingColPos { get; set; } = 1;
|
||||||
public bool HeadingTextBold { get; set; } = true;
|
/// <summary>First heading row position (from 1). Default 1. Must be > 0.</summary>
|
||||||
public bool HeadingTextWrap { get; set; } = true;
|
public uint FirstHeadingRowPos { get; set; } = 1;
|
||||||
/// <summary>Cell font colour index, ref. XlColorIndex</summary>
|
/// <summary>First data row position. Reset by SetColumnHeadings().</summary>
|
||||||
public SaXlColourIndex InteriorColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
public uint FirstDataRowPos { get; set; } = 2;
|
||||||
/// <summary>Cell RGB colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
/// <summary>Freeze column position - cell in first data row. 0 = don't freeze.</summary>
|
||||||
public int? InteriorColour { get; set; } = null;
|
public uint FreezeColPos { get; set; } = 0;
|
||||||
|
/// <summary>Font attributes. Default Arial 9 bold.</summary>
|
||||||
|
public SaMsExcelFontAttr FontAttr { get; } = new SaMsExcelFontAttr() { Name = "Arial", HeightInPoints = 9, Bold = true };
|
||||||
|
/// <summary>Whether to wrap column header cells.</summary>
|
||||||
|
public bool HeadingTextWrap { get; set; } = false;
|
||||||
|
/// <summary>Cell vertical alignment. XlVAlign.xlTop, xlCenter, xlBottom, xlJustify, xlDistributed etc.</summary>
|
||||||
|
public short? VerticalAlignment { get; set; } = null;
|
||||||
|
/// <summary>Cell foreground colour index, ref. XlColorIndex</summary>
|
||||||
|
public SaXlColourIndex ForegroundColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
||||||
|
/// <summary>Cell foreground RGB colour value, ref. XlRgbColor. Overrides foreground colour index if changed from default value.</summary>
|
||||||
|
public int? ForegroundColourRGB { get; set; } = null;
|
||||||
|
/// <summary>Cell background colour index, ref. XlColorIndex</summary>
|
||||||
|
public SaXlColourIndex BackgroundColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
||||||
public SaXlBorderWeight BorderWeight { get; set; } = SaXlBorderWeight.NotSpecified;
|
public SaXlBorderWeight BorderWeight { get; set; } = SaXlBorderWeight.NotSpecified;
|
||||||
public bool SetColumnWidths { get; set; } = true;
|
public bool SetColumnWidths { get; set; } = true;
|
||||||
public bool SetColumnAlignment { get; set; } = true;
|
public bool SetColumnAlignment { get; set; } = true;
|
||||||
@@ -147,29 +163,55 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
public class SaMsExcelFontAttr
|
public class SaMsExcelFontAttr
|
||||||
{
|
{
|
||||||
/// <summary>Font name. Arial etc.</summary>
|
/// <summary>Font name. Arial etc.</summary>
|
||||||
public String FontName { get; set; } = String.Empty;
|
public String Name { get; set; } = String.Empty;
|
||||||
/// <summary>Font style. Regular etc.</summary>
|
/// <summary>Font style. Regular etc.</summary>
|
||||||
public String FontStyle { get; set; } = String.Empty;
|
public String FontStyle { get; set; } = String.Empty;
|
||||||
public short? FontSize { get; set; } = null;
|
public double? HeightInPoints { get; set; } = null;
|
||||||
/// <summary>Font colour index, ref. XlColorIndex.</summary>
|
/// <summary>Font colour index, ref. XlColorIndex.</summary>
|
||||||
public SaXlColourIndex FontColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
public SaXlColourIndex ColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
||||||
/// <summary>Font RGB colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
/// <summary>Font RGB colour value, ref. XlRgbColor.</summary>
|
||||||
public int? FontColor { get; set; } = null;
|
public int? ColourRGB { get; set; } = null;
|
||||||
public bool? Bold { get; set; } = null;
|
public bool? Bold { get; set; } = null;
|
||||||
public bool? Strikethrough { get; set; } = null;
|
public bool? Strikethrough { get; set; } = null;
|
||||||
public bool? Superscript { get; set; } = null;
|
public bool? Superscript { get; set; } = null;
|
||||||
public bool? Subscript { get; set; } = null;
|
public bool? Subscript { get; set; } = null;
|
||||||
public bool? OutlineFont { get; set; } = null;
|
public bool? Outline { get; set; } = null;
|
||||||
public bool? Shadow { get; set; } = null;
|
public bool? Shadow { get; set; } = null;
|
||||||
public SaXlUnderlineStyle? Underline { get; set; } = null;
|
public SaXlUnderlineStyle? Underline { get; set; } = null;
|
||||||
|
public void CopyFrom(SaMsExcelFontAttr fontAttr)
|
||||||
|
{
|
||||||
|
Name = fontAttr.Name;
|
||||||
|
FontStyle = fontAttr.FontStyle;
|
||||||
|
HeightInPoints = fontAttr.HeightInPoints;
|
||||||
|
ColourIndex = fontAttr.ColourIndex;
|
||||||
|
ColourRGB = fontAttr.ColourRGB;
|
||||||
|
Bold = fontAttr.Bold;
|
||||||
|
Strikethrough = fontAttr.Strikethrough;
|
||||||
|
Superscript = fontAttr.Superscript;
|
||||||
|
Subscript = fontAttr.Subscript;
|
||||||
|
Outline = fontAttr.Outline;
|
||||||
|
Shadow = fontAttr.Shadow;
|
||||||
|
Underline = fontAttr.Underline;
|
||||||
|
}
|
||||||
|
public bool IsSpecified()
|
||||||
|
{
|
||||||
|
if (HeightInPoints != null && HeightInPoints >= SaMsSpreadsheet.FontHeightInPointsMin && HeightInPoints <= SaMsSpreadsheet.FontHeightInPointsMax) return true;
|
||||||
|
if (ColourRGB != null || ColourIndex != SaXlColourIndex.NotSpecified) return true;
|
||||||
|
if ((Bold ?? false) || (Strikethrough ?? false) || (Superscript ?? false) || (Subscript ?? false) || (Outline ?? false) || (Shadow ?? false) || (Underline != null)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
public class SaMsExcelItemAttr : SaMsExcelFontAttr
|
/// <summary>
|
||||||
|
/// Style attributes.
|
||||||
|
/// </summary>
|
||||||
|
public class SaMsExcelStyleAttr
|
||||||
{
|
{
|
||||||
// Item attributes.
|
// Item attributes.
|
||||||
|
public SaMsExcelFontAttr FontAttr { get; } = new SaMsExcelFontAttr();
|
||||||
// Attributes that are changed from their default (generally null) are set against the specified range.
|
// Attributes that are changed from their default (generally null) are set against the specified range.
|
||||||
/// <summary>Cell data format. "@"=Text etc.</summary>
|
/// <summary>Cell data format. "@"=Text etc.</summary>
|
||||||
public String NumberFormat { get; set; } = String.Empty;
|
public String DataFormat { get; set; } = String.Empty;
|
||||||
/// <summary>Cell horizontal alignment. XlHAlign.xlHAlignLeft, xlHAlignCenter, xlHAlignRight etc.</summary>
|
/// <summary>Cell horizontal alignment. XlHAlign.xlHAlignLeft, xlHAlignCenter, xlHAlignRight etc.</summary>
|
||||||
public short? HorizontalAlignment { get; set; } = null;
|
public short? HorizontalAlignment { get; set; } = null;
|
||||||
/// <summary>Cell indentation. Tabbed - left, right or distributed alignment [0 to 6]</summary>
|
/// <summary>Cell indentation. Tabbed - left, right or distributed alignment [0 to 6]</summary>
|
||||||
@@ -180,16 +222,16 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
public bool? WrapText { get; set; } = null;
|
public bool? WrapText { get; set; } = null;
|
||||||
/// <summary>Whether cells are merged.</summary>
|
/// <summary>Whether cells are merged.</summary>
|
||||||
public bool? MergeCells { get; set; } = null;
|
public bool? MergeCells { get; set; } = null;
|
||||||
/// <summary>Font colour index, ref. XlColorIndex. Black = 1 etc.</summary>
|
/// <summary>Font pattern foreground colour index, ref. XlColorIndex. Black = 1 etc.</summary>
|
||||||
public SaXlColourIndex InteriorColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
public SaXlColourIndex ForegroundColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
||||||
/// <summary>Cell RGB colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
/// <summary>Cell pattern foreground RGB colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
||||||
public int? InteriorColour { get; set; } = null;
|
public int? ForegroundColourRGB { get; set; } = null;
|
||||||
/// <summary>Cell pattern, ref. XlPattern. xlSolid etc.</summary>
|
/// <summary>Cell pattern, ref. XlPattern. xlSolid etc. NB Defaults to Solid if foreground colour specified.</summary>
|
||||||
public SaXlPattern InteriorPattern { get; set; } = SaXlPattern.NotSpecified;
|
public SaXlPattern InteriorPattern { get; set; } = SaXlPattern.NotSpecified;
|
||||||
/// <summary>Cell pattern colour index, ref. XlColorIndex. xlAutomatic etc.</summary>
|
/// <summary>Cell pattern background colour index, ref. XlColorIndex. xlAutomatic etc.</summary>
|
||||||
public SaXlColourIndex InteriorPatternColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
public SaXlColourIndex BackgroundColourIndex { get; set; } = SaXlColourIndex.NotSpecified;
|
||||||
/// <summary>Cell pattern RBG Colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
/// <summary>Cell pattern background RBG Colour value, ref. XlRgbColor. Overrides colour index if changed from default value.</summary>
|
||||||
public int? InteriorPatternColour { get; set; } = null;
|
public int? BackgroundPatternColour { get; set; } = null;
|
||||||
// Borders.
|
// Borders.
|
||||||
public SaMsExcelBorderAttr BorderLeft { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlEdgeLeft);
|
public SaMsExcelBorderAttr BorderLeft { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlEdgeLeft);
|
||||||
public SaMsExcelBorderAttr BorderTop { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlEdgeTop);
|
public SaMsExcelBorderAttr BorderTop { get; } = new SaMsExcelBorderAttr(XlBordersIndex.xlEdgeTop);
|
||||||
@@ -201,12 +243,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
List<SaMsExcelBorderAttr> borders = new List<SaMsExcelBorderAttr>();
|
return new List<SaMsExcelBorderAttr> { BorderLeft, BorderTop, BorderRight, BorderBottom };
|
||||||
borders.Add(BorderLeft);
|
|
||||||
borders.Add(BorderTop);
|
|
||||||
borders.Add(BorderRight);
|
|
||||||
borders.Add(BorderBottom);
|
|
||||||
return borders;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,9 +252,12 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Definitions.
|
// Definitions.
|
||||||
public static int FontSizeMin { get; } = 4;
|
public static double FontHeightInPointsMin { get; } = 4;
|
||||||
public static int FontSizeMax { get; } = 48;
|
public static double FontHeightInPointsMax { get; } = 48;
|
||||||
public static int NullColour { get; } = 0x4a4d4120; /* AFX_RFX_LONG_PSEUDO_NULL */
|
public static int NullColour { get; } = 0x4a4d4120; /* AFX_RFX_LONG_PSEUDO_NULL */
|
||||||
|
public const String Msg_NotSupported = "Not Supported";
|
||||||
|
public const String Msg_WorkbookNotOpen = "Workbook is not open";
|
||||||
|
public const String Msg_WorksheetNotOpen = "Worksheet is not open";
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Data members.
|
// Data members.
|
||||||
@@ -235,37 +275,55 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// W o r k b o o k
|
// Workbook.
|
||||||
//-------------------------------------------------------------------
|
|
||||||
public abstract bool IsWorkbookValid();
|
public abstract bool IsWorkbookValid();
|
||||||
public abstract bool CreateWorkbook();
|
public abstract bool CreateWorkbook();
|
||||||
public abstract bool OpenWorkbook(String filePath);
|
public abstract bool OpenWorkbook(String filePath);
|
||||||
|
/// <summary>Cleanse workbook - remove unreferenced styles etc.</summary>
|
||||||
|
public abstract bool CleanseWorkbook();
|
||||||
public abstract bool SaveDocument(String filePath, int fileFormat = (int)SaXlFileFormat.Default /* Default: XlFileFormat.xlOpenXMLWorkbook */, bool bAutomaticallyOverwrite = false);
|
public abstract bool SaveDocument(String filePath, int fileFormat = (int)SaXlFileFormat.Default /* Default: XlFileFormat.xlOpenXMLWorkbook */, bool bAutomaticallyOverwrite = false);
|
||||||
public abstract bool CloseWorkbook();
|
public abstract bool CloseWorkbook();
|
||||||
|
public abstract byte[] GetDocumentData();
|
||||||
|
// Default style.
|
||||||
|
public abstract void ApplyDefaultStyle(SaMsExcelStyleAttr attr);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// W o r k s h e e t
|
// Worksheets.
|
||||||
//-------------------------------------------------------------------
|
|
||||||
/// <summary>Is the current worksheet valid.</summary>
|
|
||||||
public abstract bool IsWorksheetValid();
|
|
||||||
/// <summary>Number of worksheets in the workbook.</summary>
|
/// <summary>Number of worksheets in the workbook.</summary>
|
||||||
public abstract uint WorksheetCount { get; }
|
public abstract uint WorksheetCount { get; }
|
||||||
/// <summary>Set the worksheets in the workbook - sheets are added or removed to match the value.</summary>
|
/// <summary>Set the worksheets in the workbook - sheets are added or removed to match the value.</summary>
|
||||||
public abstract bool SetWorksheetCount(int worksheetCount);
|
public abstract bool SetWorksheetCount(int worksheetCount);
|
||||||
|
/// <summary>Names of worksheets in the workbook.</summary>
|
||||||
|
public abstract List<String> WorksheetNames { get; }
|
||||||
|
|
||||||
/// <summary>Add a worksheet to the workbook.</summary>
|
/// <summary>Add a worksheet to the workbook.</summary>
|
||||||
public abstract bool AddWorksheet(String name);
|
public abstract bool AddWorksheet(String name);
|
||||||
/// <summary>Remove the nth worksheet - position from 1.</summary>
|
/// <summary>Remove the nth worksheet - position from 1.</summary>
|
||||||
public abstract bool RemoveWorksheet(uint worksheetPos);
|
public abstract bool RemoveWorksheet(uint worksheetPos);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Worksheet.
|
||||||
|
|
||||||
/// <summary>Open the nth worksheet - position from 1.</summary>
|
/// <summary>Open the nth worksheet - position from 1.</summary>
|
||||||
public abstract bool OpenWorksheet(uint worksheetPos);
|
public abstract bool OpenWorksheet(uint worksheetPos);
|
||||||
|
/// <summary>Open the worksheet with the specified name.</summary>
|
||||||
|
public abstract bool OpenWorksheet(String name);
|
||||||
|
/// <summary>Close the current worksheet.</summary>
|
||||||
|
public abstract bool CloseWorksheet();
|
||||||
|
|
||||||
|
/// <summary>Is the current worksheet valid.</summary>
|
||||||
|
public abstract bool IsWorksheetValid();
|
||||||
|
|
||||||
/// <summary>Get the position of the current worksheet. 0 = not open.</summary>
|
/// <summary>Get the position of the current worksheet. 0 = not open.</summary>
|
||||||
public abstract uint WorksheetPos { get; }
|
public abstract uint WorksheetPos { get; }
|
||||||
/// <summary>Get the name of the current worksheet.</summary>
|
/// <summary>Get the name of the current worksheet.</summary>
|
||||||
public abstract String WorksheetName { get; set; }
|
public abstract String WorksheetName { get; set; }
|
||||||
|
|
||||||
/// <summary>Set the default attributes for the entire worksheet</summary>
|
/// <summary>Set the default attributes for the entire worksheet</summary>
|
||||||
public abstract bool SetWorksheetAttr(SaMsExcelItemAttr attr);
|
public abstract bool SetWorksheetAttr(SaMsExcelStyleAttr attr);
|
||||||
/// <summary>Close the current worksheet.</summary>
|
|
||||||
public abstract bool CloseWorksheet();
|
|
||||||
// Worksheet Page Setup.
|
// Worksheet Page Setup.
|
||||||
/// <summary>Configure the Page Setup properties.</summary>
|
/// <summary>Configure the Page Setup properties.</summary>
|
||||||
public abstract bool SetPageSetup(SaMsExcelPageSetup_Config pageSetupConfig);
|
public abstract bool SetPageSetup(SaMsExcelPageSetup_Config pageSetupConfig);
|
||||||
@@ -273,110 +331,175 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
public abstract bool SetPageBreak(uint colPos, uint rowPos);
|
public abstract bool SetPageBreak(uint colPos, uint rowPos);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// C o l u m n s
|
// Columns.
|
||||||
//-------------------------------------------------------------------
|
|
||||||
public abstract uint GetActiveColPos();
|
public abstract uint ActiveColPos { get; }
|
||||||
public abstract double GetColWidth(uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
public abstract double GetColWidth(uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
||||||
public abstract bool SetColWidth(uint colPos, double fWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
public abstract bool SetColWidth(uint colPos, double fWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// R o w s
|
// Rows.
|
||||||
//-------------------------------------------------------------------
|
|
||||||
public abstract uint GetActiveRowPos();
|
public abstract uint FirstRowPos { get; }
|
||||||
public abstract List<DataValue> GetRowDataValues(uint rowPos, int maxColumns = 0);
|
public abstract uint LastRowPos { get; }
|
||||||
|
public abstract uint ActiveRowPos { get; }
|
||||||
|
public abstract List<DataValue> GetRowValues(uint rowPos, int maxColumns = 0);
|
||||||
public abstract double GetRowHeight(uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
public abstract double GetRowHeight(uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
||||||
public abstract bool SetRowHeight(uint rowPos, double fHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
public abstract bool SetRowHeight(uint rowPos, double fHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// C e l l s
|
// Cells.
|
||||||
//-------------------------------------------------------------------
|
|
||||||
public abstract void SetActiveCell(uint colPos, uint rowPos);
|
public abstract void SetActiveCell(uint colPos, uint rowPos);
|
||||||
|
|
||||||
public abstract String GetCellFormula(uint colPos, uint rowPos);
|
public abstract String GetCellFormula(uint colPos, uint rowPos);
|
||||||
public abstract DataValue GetCellDataValue(uint colPos, uint rowPos);
|
public abstract String GetCellText(uint colPos, uint rowPos, bool trimWhitespace = true);
|
||||||
public abstract bool SetCellFormula(uint colPos, uint rowPos, String value);
|
public abstract DataValue GetCellValue(uint colPos, uint rowPos);
|
||||||
public abstract bool SetCellFormula(uint colPos, uint rowPos, String value, SaMsExcelItemAttr attr);
|
|
||||||
public abstract bool SetRowFormulas(uint colStart, uint row, List<Object> values);
|
public abstract bool SetCellFormula(uint colPos, uint rowPos, String value, SaMsExcelStyleAttr attr = null);
|
||||||
public abstract bool SetRangeFormulas(SaMsExcelRange range, List<Object> values);
|
public abstract bool SetCellValue(uint colPos, uint rowPos, DataValue value, SaMsExcelStyleAttr attr = null);
|
||||||
|
|
||||||
|
/// <summary>Set cell formulas across a row - override if more efficient method available.</summary>
|
||||||
|
public virtual bool SetRowFormulas(uint colPosStart, uint rowPos, List<String> values)
|
||||||
|
{
|
||||||
|
for (uint colPos = Math.Max(1, colPosStart); colPos <= values.Count; colPos++)
|
||||||
|
SetCellFormula(colPos, rowPos, values[(int)(colPos - 1)]);
|
||||||
|
return !HasErrorState();
|
||||||
|
}
|
||||||
|
/// <summary>Set cell values across a row - override if more efficient method available.</summary>
|
||||||
|
public virtual bool SetRowValues(uint colPosStart, uint rowPos, List<DataValue> values)
|
||||||
|
{
|
||||||
|
for (uint colPos = Math.Max(1, colPosStart); colPos <= values.Count; colPos++)
|
||||||
|
SetCellValue(colPos, rowPos, values[(int)(colPos - 1)]);
|
||||||
|
return !HasErrorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set cell formulas across a range of cells - override if more efficient logic available.
|
||||||
|
/// <para>- Values will wrap if more cells to fill than values.</para>
|
||||||
|
public virtual bool SetRangeFormulas(SaMsExcelRange range, List<String> values)
|
||||||
|
{
|
||||||
|
if (values.IsEmpty()) return SetErrorState(SysUtil.Fn + " No values supplied");
|
||||||
|
int valueIdx = 0;
|
||||||
|
for (uint colPos = Math.Max(1, range.ColFromPos); colPos <= range.ColToPos; colPos++)
|
||||||
|
{
|
||||||
|
for (uint rowPos = Math.Max(1, range.RowFromPos); rowPos <= range.RowToPos; rowPos++)
|
||||||
|
{
|
||||||
|
// Wrap values if more cells to fill.
|
||||||
|
if (valueIdx >= values.Count)
|
||||||
|
valueIdx = 0;
|
||||||
|
SetCellFormula(colPos, rowPos, values[valueIdx++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !HasErrorState();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Set cell values across a range of cells - override if more efficient logic available.
|
||||||
|
/// <para>- Values will wrap if more cells to fill than values.</para>
|
||||||
|
public virtual bool SetRangeValues(SaMsExcelRange range, List<DataValue> values)
|
||||||
|
{
|
||||||
|
if (values.IsEmpty()) return SetErrorState(SysUtil.Fn + " No values supplied");
|
||||||
|
int valueIdx = 0;
|
||||||
|
for (uint colPos = Math.Max(1, range.ColFromPos); colPos <= range.ColToPos; colPos++)
|
||||||
|
{
|
||||||
|
for (uint rowPos = Math.Max(1, range.RowFromPos); rowPos <= range.RowToPos; rowPos++)
|
||||||
|
{
|
||||||
|
// Wrap values if more cells to fill.
|
||||||
|
if (valueIdx >= values.Count)
|
||||||
|
valueIdx = 0;
|
||||||
|
SetCellValue(colPos, rowPos, values[valueIdx++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !HasErrorState();
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Populate headings.
|
// Populate headings.
|
||||||
public bool SetColumnHeadings(List<ColumnDfn> columns, SaMsExcelColumnHeading_Config config)
|
public bool SetColumnHeadings(List<ColumnDfn> columns, SaMsExcelColumnHeading_Config headingConfig)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
double columnWidthPixelsPerCm = Math.Min(100.0, Math.Max(10.0, config.ColumnWidthPixelsPerCm));
|
double columnWidthPixelsPerCm = Math.Min(100.0, Math.Max(10.0, headingConfig.ColumnWidthPixelsPerCm));
|
||||||
uint firstHeadingRow = (uint)Math.Max(1, config.FirstHeadingRow);
|
uint firstHeadingRowPos = (uint)Math.Max(1, headingConfig.FirstHeadingRowPos);
|
||||||
|
// Assume only a single header row.
|
||||||
|
headingConfig.FirstDataRowPos = firstHeadingRowPos + 1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Populate default heading cell attributes.
|
// Populate default heading cell attributes.
|
||||||
SaMsExcelItemAttr attrHdrDefault = new SaMsExcelItemAttr();
|
SaMsExcelStyleAttr attrHdrDefault = new SaMsExcelStyleAttr();
|
||||||
attrHdrDefault.Bold = config.HeadingTextBold;
|
attrHdrDefault.FontAttr.CopyFrom(headingConfig.FontAttr);
|
||||||
attrHdrDefault.FontSize = (short)Math.Min(80, Math.Max(2, (int)config.HeadingFontSize));
|
attrHdrDefault.WrapText = headingConfig.HeadingTextWrap ? true : null;
|
||||||
attrHdrDefault.InteriorColourIndex = config.InteriorColourIndex;
|
attrHdrDefault.VerticalAlignment = headingConfig.VerticalAlignment;
|
||||||
if (config.InteriorColour != null)
|
attrHdrDefault.ForegroundColourIndex = headingConfig.ForegroundColourIndex;
|
||||||
attrHdrDefault.InteriorColour = config.InteriorColour;
|
attrHdrDefault.BackgroundColourIndex = headingConfig.BackgroundColourIndex;
|
||||||
if (config.BorderWeight != SaXlBorderWeight.NotSpecified)
|
if (headingConfig.ForegroundColourRGB != null)
|
||||||
|
attrHdrDefault.ForegroundColourRGB = headingConfig.ForegroundColourRGB;
|
||||||
|
if (headingConfig.BorderWeight != SaXlBorderWeight.NotSpecified)
|
||||||
{
|
{
|
||||||
attrHdrDefault.BorderLeft.Weight = config.BorderWeight;
|
attrHdrDefault.BorderLeft.Weight = headingConfig.BorderWeight;
|
||||||
attrHdrDefault.BorderTop.Weight = config.BorderWeight;
|
attrHdrDefault.BorderTop.Weight = headingConfig.BorderWeight;
|
||||||
attrHdrDefault.BorderRight.Weight = config.BorderWeight;
|
attrHdrDefault.BorderRight.Weight = headingConfig.BorderWeight;
|
||||||
attrHdrDefault.BorderBottom.Weight = config.BorderWeight;
|
attrHdrDefault.BorderBottom.Weight = headingConfig.BorderWeight;
|
||||||
attrHdrDefault.BorderInsideVertical.Weight = config.BorderWeight;
|
|
||||||
}
|
}
|
||||||
SaMsExcelRange rangeHeadings = new SaMsExcelRange(config.FirstHeadingColumn, firstHeadingRow, (uint)(config.FirstHeadingColumn + columns.Count - 1), firstHeadingRow);
|
SaMsExcelRange rangeHeadings = new SaMsExcelRange(headingConfig.FirstHeadingColPos, firstHeadingRowPos, (uint)(headingConfig.FirstHeadingColPos + columns.Count - 1), firstHeadingRowPos);
|
||||||
SetRangeAttr(rangeHeadings, attrHdrDefault);
|
SetRangeAttr(rangeHeadings, attrHdrDefault);
|
||||||
|
|
||||||
// Set default column attributes.
|
// Set default column attributes.
|
||||||
bool defaultColumnAttributesPopulated = false;
|
bool defaultColumnAttributesPopulated = false;
|
||||||
SaMsExcelItemAttr attrColDefault = new SaMsExcelItemAttr();
|
SaMsExcelStyleAttr attrColDefault = new SaMsExcelStyleAttr();
|
||||||
if (config.SetColumnAlignment)
|
if (headingConfig.SetColumnAlignment)
|
||||||
{
|
{
|
||||||
attrColDefault.HorizontalAlignment = (short)XlHAlign.xlHAlignLeft;
|
attrColDefault.HorizontalAlignment = (short)XlHAlign.xlHAlignLeft;
|
||||||
defaultColumnAttributesPopulated = true;
|
defaultColumnAttributesPopulated = true;
|
||||||
}
|
}
|
||||||
if (config.SetColumnDataTypeFormat)
|
if (headingConfig.SetColumnDataTypeFormat)
|
||||||
{
|
{
|
||||||
attrColDefault.NumberFormat = "@"; // '@' = 'Text' format.
|
attrColDefault.DataFormat = "@"; // '@' = 'Text' format.
|
||||||
defaultColumnAttributesPopulated = true;
|
defaultColumnAttributesPopulated = true;
|
||||||
}
|
}
|
||||||
if (defaultColumnAttributesPopulated)
|
if (defaultColumnAttributesPopulated)
|
||||||
{
|
{
|
||||||
SaMsExcelRange rangeColumns = new SaMsExcelRange(config.FirstHeadingColumn, 0, (uint)(config.FirstHeadingColumn + columns.Count - 1), 0);
|
SaMsExcelRange rangeColumns = new SaMsExcelRange(headingConfig.FirstHeadingColPos, 0, (uint)(headingConfig.FirstHeadingColPos + columns.Count - 1), 0);
|
||||||
SetRangeAttr(rangeColumns, attrColDefault);
|
SetRangeAttr(rangeColumns, attrColDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate column headings and specific styles.
|
// Populate column styling and headings.
|
||||||
List<Object> values = new List<Object>();
|
List<DataValue> columnHeadings = new List<DataValue>();
|
||||||
for (int columnIdx = 0; columnIdx < columns.Count; columnIdx++)
|
for (int columnIdx = 0; columnIdx < columns.Count; columnIdx++)
|
||||||
{
|
{
|
||||||
ColumnDfn column = columns[columnIdx];
|
ColumnDfn column = columns[columnIdx];
|
||||||
uint col = (uint)(Math.Max(1, config.FirstHeadingColumn) + columnIdx);
|
uint colPos = (uint)(Math.Max(1, headingConfig.FirstHeadingColPos) + columnIdx);
|
||||||
SaMsExcelRange range = new SaMsExcelRange(col, firstHeadingRow);
|
SaMsExcelRange range = new SaMsExcelRange(colPos, firstHeadingRowPos);
|
||||||
|
|
||||||
// Specific heading cell attributes - none supported as yet.
|
// Specific heading cell attributes.
|
||||||
bool headingCellHasSpecificAttr = false;
|
bool headingCellHasSpecificAttr = false;
|
||||||
SaMsExcelItemAttr attrHdr = new SaMsExcelItemAttr();
|
SaMsExcelStyleAttr attrHdr = new SaMsExcelStyleAttr();
|
||||||
if (headingCellHasSpecificAttr)
|
if (headingCellHasSpecificAttr)
|
||||||
SetRangeAttr(range, attrHdr);
|
SetRangeAttr(range, attrHdr);
|
||||||
|
|
||||||
// Column width and caption:
|
// Column width and caption:
|
||||||
if (config.SetColumnWidths) SetColWidth(col, column.Width / columnWidthPixelsPerCm, SaExcelLogicalUnit.Cm);
|
if (headingConfig.SetColumnWidths) SetColWidth(colPos, column.Width * 1.5 / columnWidthPixelsPerCm, SaExcelLogicalUnit.Cm);
|
||||||
values.Add(column.Caption);
|
columnHeadings.Add(column.Caption);
|
||||||
|
|
||||||
// Column attributes:
|
// Column attributes:
|
||||||
bool columnHasSpecificAttributes = false;
|
bool columnHasSpecificStyle = false;
|
||||||
SaMsExcelItemAttr attrCol = new SaMsExcelItemAttr();
|
SaMsExcelStyleAttr attrCol = new SaMsExcelStyleAttr();
|
||||||
if (config.SetColumnAlignment && column.Alignment != ColumnAlignment.Left && column.Alignment != ColumnAlignment.Default)
|
if (headingConfig.SetColumnAlignment && column.Alignment != ColumnAlignment.Left && column.Alignment != ColumnAlignment.Default)
|
||||||
{
|
{
|
||||||
columnHasSpecificAttributes = true;
|
columnHasSpecificStyle = true;
|
||||||
switch (column.Alignment)
|
switch (column.Alignment)
|
||||||
{
|
{
|
||||||
case ColumnAlignment.Center: attrCol.HorizontalAlignment = (short)XlHAlign.xlHAlignCenter; break;
|
case ColumnAlignment.Center: attrCol.HorizontalAlignment = (short)XlHAlign.xlHAlignCenter; break;
|
||||||
case ColumnAlignment.Right: attrCol.HorizontalAlignment = (short)XlHAlign.xlHAlignRight; break;
|
case ColumnAlignment.Right: attrCol.HorizontalAlignment = (short)XlHAlign.xlHAlignRight; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (config.SetColumnDataTypeFormat && column.DataType != DataValue.DataType.String)
|
if (column.WrapText)
|
||||||
{
|
{
|
||||||
columnHasSpecificAttributes = true;
|
columnHasSpecificStyle = true;
|
||||||
|
attrCol.WrapText = true;
|
||||||
|
}
|
||||||
|
if (headingConfig.SetColumnDataTypeFormat && column.DataType != DataValue.DataType.String)
|
||||||
|
{
|
||||||
|
columnHasSpecificStyle = true;
|
||||||
if (column.DataType == DataValue.DataType.Long || column.DataType == DataValue.DataType.Double || column.DataType == DataValue.DataType.Decimal)
|
if (column.DataType == DataValue.DataType.Long || column.DataType == DataValue.DataType.Double || column.DataType == DataValue.DataType.Decimal)
|
||||||
{
|
{
|
||||||
// Numeric format: "#,##0.00"
|
// Numeric format: "#,##0.00"
|
||||||
@@ -388,63 +511,66 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
if ((column.DataType == DataValue.DataType.Double || column.DataType == DataValue.DataType.Decimal) && column.NumDecimals > 0)
|
if ((column.DataType == DataValue.DataType.Double || column.DataType == DataValue.DataType.Decimal) && column.NumDecimals > 0)
|
||||||
numberFormat += "." + "0".PadRight(column.NumDecimals, '0');
|
numberFormat += "." + "0".PadRight(column.NumDecimals, '0');
|
||||||
attrCol.NumberFormat = numberFormat + ";[Red]-" + numberFormat;
|
attrCol.DataFormat = numberFormat + ";[Red]-" + numberFormat;
|
||||||
}
|
}
|
||||||
else if (column.DataType == DataValue.DataType.Date) attrCol.NumberFormat = config.CellFormatDate;
|
else if (column.DataType == DataValue.DataType.Date) attrCol.DataFormat = headingConfig.CellFormatDate;
|
||||||
else if (column.DataType == DataValue.DataType.Time) attrCol.NumberFormat = config.CellFormatTime;
|
else if (column.DataType == DataValue.DataType.Time) attrCol.DataFormat = headingConfig.CellFormatTime;
|
||||||
else if (column.DataType == DataValue.DataType.DateTime) attrCol.NumberFormat = config.CellFormatDate + config.CellFormatDateTimeDelim + config.CellFormatTime;
|
else if (column.DataType == DataValue.DataType.DateTime) attrCol.DataFormat = headingConfig.CellFormatDate + headingConfig.CellFormatDateTimeDelim + headingConfig.CellFormatTime;
|
||||||
}
|
}
|
||||||
if (columnHasSpecificAttributes)
|
if (columnHasSpecificStyle)
|
||||||
SetRangeAttr(new SaMsExcelRange(col, 0), attrCol);
|
SetRangeAttr(new SaMsExcelRange(colPos, 0), attrCol);
|
||||||
// Freeze the window below if a colmn has been specified:
|
// Freeze the window below if a colmn has been specified:
|
||||||
if (config.FreezeColumn > 0) FreezePanes(config.FreezeColumn, firstHeadingRow + 1);
|
if (headingConfig.FreezeColPos > 0) FreezePanes(headingConfig.FreezeColPos, firstHeadingRowPos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate header captions.
|
// Populate header captions.
|
||||||
SetRowFormulas(config.FirstHeadingColumn, firstHeadingRow, values);
|
SetRowValues(headingConfig.FirstHeadingColPos, firstHeadingRowPos, columnHeadings);
|
||||||
// Set header row to wrap text:
|
|
||||||
if (config.HeadingTextWrap)
|
// Auto fit header row if text is wrapped:
|
||||||
{
|
if (headingConfig.HeadingTextWrap)
|
||||||
SaMsExcelItemAttr attrRow = new SaMsExcelItemAttr();
|
AutoFitRows(rangeHeadings);
|
||||||
attrRow.WrapText = true;
|
|
||||||
SetRangeAttr(new SaMsExcelRange(0, firstHeadingRow), attrRow);
|
|
||||||
// Auto fit the header row (set height to fit text):
|
|
||||||
AutoFit(new SaMsExcelRange(0, firstHeadingRow));
|
|
||||||
}
|
}
|
||||||
}
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
catch (Exception exc) { HandleException("SetColumnHeadings", exc); }
|
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Cell attributes.
|
// Cell attributes.
|
||||||
public abstract bool SetRangeAttr(SaMsExcelRange range, SaMsExcelItemAttr attr);
|
public abstract bool SetRangeAttr(SaMsExcelRange range, SaMsExcelStyleAttr attr);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
// Add image to sheet.
|
// Add image to sheet.
|
||||||
public abstract bool InsertImage(SaMsExcelImage_Config imageConfig);
|
public abstract bool InsertImage(SaMsExcelImage_Config imageConfig);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
/// <summary>Freeze sheet at specified cell.</summary>
|
||||||
public abstract bool FreezePanes(uint colPos, uint rowPos);
|
public abstract bool FreezePanes(uint colPos, uint rowPos);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
/// <summary>Auto-fit row heights to contents.</summary>
|
||||||
public abstract bool AutoFit(SaMsExcelRange range);
|
public abstract bool AutoFitRows(SaMsExcelRange range);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
/// <summary>Select range of cells.</summary>
|
||||||
public abstract bool SelectRange(SaMsExcelRange range);
|
public abstract bool SelectRange(SaMsExcelRange range);
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Utilities.
|
// Utilities.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert cell range to Id.
|
||||||
|
/// <para>- Not fixed: "A9:AB34"</para>
|
||||||
|
/// <para>- Fixed cols: "$A9:$AB34"</para>
|
||||||
|
/// <para>- Fixed rows: "A$9:AB$34"</para>
|
||||||
|
/// <para>- Fixed: "$A$9:$AB$34"</para>
|
||||||
|
/// </summary>
|
||||||
public static String GetRangeId(SaMsExcelRange range, bool fixedCols = false, bool fixedRows = false)
|
public static String GetRangeId(SaMsExcelRange range, bool fixedCols = false, bool fixedRows = false)
|
||||||
{
|
{
|
||||||
// Not fixed: "A9:AB34"
|
return GetColumnIdPrefix(range.ColFromPos, fixedCols) + GetRowIdSuffix(range.RowFromPos, fixedRows) + ":" + GetColumnIdPrefix(range.ColToPos, fixedCols) + GetRowIdSuffix(range.RowToPos, fixedRows);
|
||||||
// Fixed cols: "$A9:$AB34"
|
|
||||||
// Fixed rows: "A$9:AB$34"
|
|
||||||
// Fixed: "$A$9:$AB$34"
|
|
||||||
return (fixedCols ? "$" : "") + GetColumnPrefix(range.ColFrom) + (fixedRows ? "$" : "") + GetRowSuffix(range.RowFrom) + ":" + (fixedCols ? "$" : "") + GetColumnPrefix(range.ColTo) + (fixedRows ? "$" : "") + GetRowSuffix(range.RowTo);
|
|
||||||
}
|
}
|
||||||
public static String GetColumnPrefix(uint colPos)
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert column position to Id prefix. 1=A,2=B,3=C...26=Z,27=AA,28=AB etc.
|
||||||
|
/// <para>- Fixed prefixes with '$'.</para>
|
||||||
|
/// </summary>
|
||||||
|
public static String GetColumnIdPrefix(uint colPos, bool fixedCol = false)
|
||||||
{
|
{
|
||||||
// 1=A,2=B,3=C...26=Z,27=AA,28=AB etc
|
|
||||||
uint dividend = colPos;
|
uint dividend = colPos;
|
||||||
string columnName = String.Empty;
|
string columnName = String.Empty;
|
||||||
uint modulo = 0;
|
uint modulo = 0;
|
||||||
@@ -454,35 +580,51 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
|
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
|
||||||
dividend = (uint)((dividend - modulo) / 26);
|
dividend = (uint)((dividend - modulo) / 26);
|
||||||
}
|
}
|
||||||
return columnName;
|
return (fixedCol ? "$" : "") + columnName;
|
||||||
}
|
}
|
||||||
public static int GetIndexForCol(String column)
|
|
||||||
|
/// <summary>Convert column Id to position. A=1,B=2,C=3...Z=26,AA=27 etc.</summary>
|
||||||
|
public static int GetPosForColId(String colId)
|
||||||
{
|
{
|
||||||
// A=1,B=2,C=3...Z=26,AA=27 etc
|
colId = StringUtil.TrimWhitespace(StringUtil.OnBlank(colId)).ToUpper();
|
||||||
int col = (column[0] - 'A');
|
if (!colId.Matches(new Regex("[A-Z]+")))
|
||||||
if (column.Length > 1)
|
{
|
||||||
col = (column[1] * 26) + column[0];
|
SaLogger.Warn(SysUtil.Fn + " Invalid column Id supplied: '" + colId + "'");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int col = (colId[0] - 'A');
|
||||||
|
if (colId.Length > 1)
|
||||||
|
col = ((colId[1] - 'A') * 26) + (colId[0] - 'A');
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Column Id - To reference entire column: A:A,B:A,C:A...Z:Z,AA:AA etc.</summary>
|
||||||
public static String GetColumnId(uint colPos)
|
public static String GetColumnId(uint colPos)
|
||||||
{
|
{
|
||||||
// To reference entire column: A:A,B:A,C:A...Z:Z,AA:AA etc
|
return GetColumnIdPrefix(colPos) + ":" + GetColumnIdPrefix(colPos);
|
||||||
return GetColumnPrefix(colPos) + ":" + GetColumnPrefix(colPos);
|
|
||||||
}
|
}
|
||||||
public static String GetRowSuffix(uint rowPos)
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert row pos to id suffix. 1=1,2=2,3=3...26=26,27=27,28=28 etc.
|
||||||
|
/// <para>- Fixed prefixes with '$'.</para>
|
||||||
|
/// </summary>
|
||||||
|
public static String GetRowIdSuffix(uint rowPos, bool fixedRow = false)
|
||||||
{
|
{
|
||||||
// 1,2,3...26,27,28 etc
|
return (rowPos > 0 ? (fixedRow ? "$" : "") + rowPos.ToString() : "");
|
||||||
return (rowPos > 0 ? rowPos.ToString() : "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Row id - To reference entire row: 1:1,2:2,3:3 etc.</summary>
|
||||||
public static String GetRowId(uint rowPos)
|
public static String GetRowId(uint rowPos)
|
||||||
{
|
{
|
||||||
// To reference entire row: 1:1,2:2,3:3 etc
|
return GetRowIdSuffix(rowPos) + ":" + GetRowIdSuffix(rowPos);
|
||||||
return GetRowSuffix(rowPos) + ":" + GetRowSuffix(rowPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Convert cell by column and row positions to Id.</summary>
|
||||||
public static String GetCellId(uint colPos, uint rowPos)
|
public static String GetCellId(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
return GetColumnPrefix(colPos) + GetRowSuffix(rowPos);
|
return GetColumnIdPrefix(colPos) + GetRowIdSuffix(rowPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DateTime ExtractDate(String value)
|
public static DateTime ExtractDate(String value)
|
||||||
{
|
{
|
||||||
DateTime date = DateTime.MinValue;
|
DateTime date = DateTime.MinValue;
|
||||||
@@ -502,7 +644,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public static double PointsPerInch { get; } = 72;
|
public static double PointsPerInch { get; } = 72;
|
||||||
public static double PixelsPerInch { get; } = 96;
|
public static double PixelsPerInch { get; } = 96;
|
||||||
public static double CmsPerInch { get; } = 2.54f;
|
public static double CmsPerInch { get; } = 2.54;
|
||||||
public double ConvertLength(double fLength, SaExcelLogicalUnit eUnitFrom, SaExcelLogicalUnit eUnitTo, bool bVertical)
|
public double ConvertLength(double fLength, SaExcelLogicalUnit eUnitFrom, SaExcelLogicalUnit eUnitTo, bool bVertical)
|
||||||
{
|
{
|
||||||
// Convert length to points:
|
// Convert length to points:
|
||||||
@@ -559,7 +701,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
protected void HandleException(String fn, Exception exc)
|
protected void HandleException(String fn, Exception exc)
|
||||||
{
|
{
|
||||||
SaLogger.Error(GetType().Name + "." + fn + " " + ExceptionUtil.GetLogMessage(exc));
|
SaLogger.Error(fn + " " + ExceptionUtil.GetLogMessage(exc));
|
||||||
SetErrorState("Problems were encountered interfacing to Excel - " + ExceptionUtil.GetErrorStateMessage(exc));
|
SetErrorState("Problems were encountered interfacing to Excel - " + ExceptionUtil.GetErrorStateMessage(exc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
/// <summary>Style properties retrieved directly from spreadsheet xml data.</summary>
|
/// <summary>Style properties retrieved directly from spreadsheet xml data.</summary>
|
||||||
public class SaMsExcelStyle
|
public class SaMsExcelStyle
|
||||||
{
|
{
|
||||||
public SaMsExcelStyle () { }
|
public SaMsExcelStyle() { }
|
||||||
public int NumFmtId { get; set; }
|
public int NumFmtId { get; set; }
|
||||||
public int FontId { get; set; }
|
public int FontId { get; set; }
|
||||||
public int FillId { get; set; }
|
public int FillId { get; set; }
|
||||||
@@ -51,7 +51,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
internal SaMsXmlDocument StylesDoc { get; set; }
|
internal SaMsXmlDocument StylesDoc { get; set; }
|
||||||
internal uint WorksheetCount { get; set; }
|
internal uint WorksheetCount { get; set; }
|
||||||
internal uint ActiveSheetPos { get; set; }
|
internal uint ActiveSheetPos { get; set; }
|
||||||
internal bool IsValid () { return (WorkbookDoc != null && WorkbookDoc.GetRootElement() != null); }
|
internal bool IsValid() { return (WorkbookDoc != null && WorkbookDoc.GetRootElement() != null); }
|
||||||
}
|
}
|
||||||
private Workbook workbook;
|
private Workbook workbook;
|
||||||
private class Worksheet
|
private class Worksheet
|
||||||
@@ -71,17 +71,17 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
internal SaMsXmlElement ActiveRow { get; set; }
|
internal SaMsXmlElement ActiveRow { get; set; }
|
||||||
}
|
}
|
||||||
internal NodesData Nodes { get; } = new NodesData();
|
internal NodesData Nodes { get; } = new NodesData();
|
||||||
bool IsValid () { return (WorksheetDoc != null && WorksheetDoc.GetRootElement() != null); }
|
bool IsValid() { return (WorksheetDoc != null && WorksheetDoc.GetRootElement() != null); }
|
||||||
|
|
||||||
}
|
}
|
||||||
private Worksheet worksheet;
|
private Worksheet worksheet;
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Construction.
|
// Construction.
|
||||||
public SaMsSpreadsheet_Direct () : base()
|
public SaMsSpreadsheet_Direct() : base()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
protected override void Dispose (bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
@@ -96,11 +96,11 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// W o r k b o o k
|
// W o r k b o o k
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override bool IsWorkbookValid ()
|
public override bool IsWorkbookValid()
|
||||||
{
|
{
|
||||||
return (workbook != null && workbook.IsValid());
|
return (workbook != null && workbook.IsValid());
|
||||||
}
|
}
|
||||||
public override bool CreateWorkbook ()
|
public override bool CreateWorkbook()
|
||||||
{
|
{
|
||||||
CloseWorkbook();
|
CloseWorkbook();
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
@@ -113,7 +113,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
|
|
||||||
return SetErrorState("Creating workbook not supported");
|
return SetErrorState("Creating workbook not supported");
|
||||||
}
|
}
|
||||||
public override bool OpenWorkbook (String filePath)
|
public override bool OpenWorkbook(String filePath)
|
||||||
{
|
{
|
||||||
CloseWorkbook();
|
CloseWorkbook();
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
@@ -138,7 +138,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
public bool OpenWorkbook (byte[] workbookData)
|
public bool OpenWorkbook(byte[] workbookData)
|
||||||
{
|
{
|
||||||
CloseWorkbook();
|
CloseWorkbook();
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
@@ -152,7 +152,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
public bool OpenWorkbook (Stream workbookStream)
|
public bool OpenWorkbook(Stream workbookStream)
|
||||||
{
|
{
|
||||||
CloseWorkbook();
|
CloseWorkbook();
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
@@ -172,7 +172,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
private bool ExtractWorkbookElementsFromArchive ()
|
private bool ExtractWorkbookElementsFromArchive()
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
@@ -214,19 +214,22 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
catch (Exception exc) { SetErrorState(ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
public override bool SaveDocument (String filePath, int fileFormat, bool bAutomaticallyOverwrite)
|
public override bool CleanseWorkbook()
|
||||||
|
{
|
||||||
|
throw new NotSupportedException(SysUtil.Fn);
|
||||||
|
}
|
||||||
|
public override bool SaveDocument(String filePath, int fileFormat, bool bAutomaticallyOverwrite)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
if (fileFormat == 0)
|
if (fileFormat == 0)
|
||||||
fileFormat = (int)XlFileFormat.xlOpenXMLWorkbook;
|
fileFormat = (int)XlFileFormat.xlOpenXMLWorkbook;
|
||||||
if (fileFormat != (int)XlFileFormat.xlOpenXMLWorkbook)
|
if (fileFormat != (int)XlFileFormat.xlOpenXMLWorkbook)
|
||||||
SetErrorState("Unsupported file format: " + ((XlFileFormat)fileFormat).ToString());
|
return SetErrorState("Unsupported file format: " + ((XlFileFormat)fileFormat).ToString());
|
||||||
if (!HasErrorState() && !workbook.IsValid())
|
if (!IsWorkbookValid()) SetErrorState(Msg_WorkbookNotOpen);
|
||||||
SetErrorState("Workbook is not open");
|
|
||||||
SetErrorState("Saving workbook not supported");
|
SetErrorState("Saving workbook not supported");
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
public override bool CloseWorkbook ()
|
public override bool CloseWorkbook()
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
CloseWorksheet();
|
CloseWorksheet();
|
||||||
@@ -247,15 +250,25 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
/// <summary>Extract the document as a byte array.</summary>
|
||||||
// W o r k s h e e t
|
/// <returns>Document data as byte array.</returns>
|
||||||
//-------------------------------------------------------------------
|
public override byte[] GetDocumentData()
|
||||||
public override bool IsWorksheetValid ()
|
|
||||||
{
|
{
|
||||||
return (worksheet != null && worksheet.WorksheetDoc != null);
|
throw new NotSupportedException(SysUtil.Fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default style.
|
||||||
|
public override void ApplyDefaultStyle(SaMsExcelStyleAttr attr)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException(SysUtil.Fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// W o r k s h e e t s
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
public override uint WorksheetCount { get { return workbook.WorksheetCount; } }
|
public override uint WorksheetCount { get { return workbook.WorksheetCount; } }
|
||||||
private void PopulateWorksheetCount ()
|
private void PopulateWorksheetCount()
|
||||||
{
|
{
|
||||||
if (!IsWorkbookValid()) return;
|
if (!IsWorkbookValid()) return;
|
||||||
try
|
try
|
||||||
@@ -265,25 +278,32 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
SaMsXmlElement nodeSheets = nodeWorkbook.GetFirstChildElement("sheets");
|
SaMsXmlElement nodeSheets = nodeWorkbook.GetFirstChildElement("sheets");
|
||||||
workbook.WorksheetCount = (uint)nodeSheets.GetChildElements("sheet").Count;
|
workbook.WorksheetCount = (uint)nodeSheets.GetChildElements("sheet").Count;
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetWorksheetCount", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
}
|
}
|
||||||
public override bool SetWorksheetCount (int worksheetCount)
|
public override bool SetWorksheetCount(int worksheetCount)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
return SetErrorState("Modifying workbook not supported");
|
return SetErrorState("Modifying workbook not supported");
|
||||||
}
|
}
|
||||||
public override bool AddWorksheet(String name)
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override List<String> WorksheetNames
|
||||||
{
|
{
|
||||||
return SetErrorState("Modifying workbook not supported");
|
get
|
||||||
}
|
|
||||||
public override bool RemoveWorksheet(uint worksheetPos)
|
|
||||||
{
|
{
|
||||||
return SetErrorState("Modifying workbook not supported");
|
List<String> names = new List<String>();
|
||||||
|
return names;
|
||||||
}
|
}
|
||||||
public override bool OpenWorksheet (uint worksheetPos)
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Open worksheet by position (from 1).
|
||||||
|
/// </summary>
|
||||||
|
public override bool OpenWorksheet(uint worksheetPos)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
if (!workbook.IsValid()) return SetErrorState("Workbook is not open");
|
if (!IsWorkbookValid()) return SetErrorState(Msg_WorkbookNotOpen);
|
||||||
if (worksheetPos > WorksheetCount) return SetErrorState("Invalid sheet specified");
|
if (worksheetPos > WorksheetCount) return SetErrorState("Invalid sheet specified");
|
||||||
if (worksheetPos <= 0) worksheetPos = Math.Max(1, workbook.ActiveSheetPos);
|
if (worksheetPos <= 0) worksheetPos = Math.Max(1, workbook.ActiveSheetPos);
|
||||||
CloseWorksheet();
|
CloseWorksheet();
|
||||||
@@ -329,20 +349,70 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
if (worksheet.WorksheetDoc == null) return SetErrorState("Unable to load worksheet " + worksheetPos.ToString());
|
if (worksheet.WorksheetDoc == null) return SetErrorState("Unable to load worksheet " + worksheetPos.ToString());
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("OpenWorksheet", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
public override uint WorksheetPos { get { return workbook.ActiveSheetPos; } }
|
|
||||||
public override String WorksheetName
|
//-------------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Open worksheet by position (from 1).
|
||||||
|
/// </summary>
|
||||||
|
public override bool OpenWorksheet(String name)
|
||||||
{
|
{
|
||||||
get { return ""; }
|
ClearErrorState();
|
||||||
set { }
|
if (!IsWorkbookValid()) return SetErrorState(Msg_WorkbookNotOpen);
|
||||||
}
|
CloseWorksheet();
|
||||||
public override bool SetWorksheetAttr (SaMsExcelItemAttr attr)
|
name = StringUtil.TrimWhitespace(name);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
worksheet = new Worksheet();
|
||||||
|
// Locate worksheet in workbook by 0-index.
|
||||||
|
SaMsXmlElement workbookElement = workbook.WorkbookDoc.GetRootElement();
|
||||||
|
SaMsXmlElement sheetsElement = workbookElement.GetFirstChildElement("sheets");
|
||||||
|
uint worksheetPos = 0;
|
||||||
|
foreach (SaMsXmlElement sheetElement in sheetsElement.GetChildElements("sheet"))
|
||||||
|
{
|
||||||
|
worksheetPos++;
|
||||||
|
String sheetName = sheetElement.GetAttributeValue("name");
|
||||||
|
if (StringUtil.TrimWhitespace(sheetName).EqualsCI(name))
|
||||||
|
{
|
||||||
|
// 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 = sheetName;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
public override bool CloseWorksheet ()
|
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(SysUtil.Fn, exc); }
|
||||||
|
return !HasErrorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override bool CloseWorksheet()
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
|
|
||||||
@@ -364,24 +434,51 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Worksheet Page Setup.
|
public override bool AddWorksheet(String name)
|
||||||
public override bool SetPageSetup (SaMsExcelPageSetup_Config pageSetupConfig)
|
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState("Modifying workbook not supported");
|
||||||
}
|
}
|
||||||
public override bool SetPageBreak (uint col, uint row)
|
public override bool RemoveWorksheet(uint worksheetPos)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState("Modifying workbook not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// W o r k s h e e t
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override bool IsWorksheetValid()
|
||||||
|
{
|
||||||
|
return (worksheet != null && worksheet.WorksheetDoc != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override uint WorksheetPos { get { return workbook.ActiveSheetPos; } }
|
||||||
|
public override String WorksheetName
|
||||||
|
{
|
||||||
|
get { return ""; }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
public override bool SetWorksheetAttr(SaMsExcelStyleAttr attr)
|
||||||
|
{
|
||||||
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Worksheet Page Setup.
|
||||||
|
public override bool SetPageSetup(SaMsExcelPageSetup_Config pageSetupConfig)
|
||||||
|
{
|
||||||
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
|
}
|
||||||
|
public override bool SetPageBreak(uint col, uint row)
|
||||||
|
{
|
||||||
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// C o l u m n s
|
// C o l u m n s
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override uint GetActiveColPos ()
|
public override uint ActiveColPos { get { return worksheet.ActiveColPos; } }
|
||||||
{
|
private SaMsXmlElement GetColElement(uint colPos)
|
||||||
return worksheet.ActiveColPos;
|
|
||||||
}
|
|
||||||
private SaMsXmlElement GetColElement (uint colPos)
|
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
@@ -399,10 +496,10 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetColElement", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return new SaMsXmlElement(null);
|
return new SaMsXmlElement(null);
|
||||||
}
|
}
|
||||||
public override double GetColWidth (uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
public override double GetColWidth(uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
@@ -416,22 +513,35 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
if (unit == SaExcelLogicalUnit.Inch) return PointsToInches(width);
|
if (unit == SaExcelLogicalUnit.Inch) return PointsToInches(width);
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetColWidth", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
public override bool SetColWidth (uint colPos, double fWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
public override bool SetColWidth(uint colPos, double fWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// R o w s
|
// R o w s
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override uint GetActiveRowPos ()
|
public override uint FirstRowPos
|
||||||
{
|
{
|
||||||
return worksheet.ActiveRowPos;
|
get
|
||||||
|
{
|
||||||
|
SaMsXmlElement rowElement = worksheet.Nodes.Rows.GetChildElements("row").First();
|
||||||
|
return (uint)(rowElement?.GetAttributeValue("r").ToLong() ?? 0);
|
||||||
}
|
}
|
||||||
SaMsXmlElement GetRowElement (uint rowPos)
|
}
|
||||||
|
public override uint LastRowPos
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
SaMsXmlElement rowElement = worksheet.Nodes.Rows.GetChildElements("row").Last();
|
||||||
|
return (uint)(rowElement?.GetAttributeValue("r").ToLong() ?? 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override uint ActiveRowPos { get { return worksheet.ActiveRowPos; } }
|
||||||
|
SaMsXmlElement GetRowElement(uint rowPos)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
@@ -448,10 +558,10 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetRowElement", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return new SaMsXmlElement(null);
|
return new SaMsXmlElement(null);
|
||||||
}
|
}
|
||||||
public override double GetRowHeight (uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
public override double GetRowHeight(uint rowPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
@@ -465,18 +575,18 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
if (unit == SaExcelLogicalUnit.Inch) return PointsToInches(height);
|
if (unit == SaExcelLogicalUnit.Inch) return PointsToInches(height);
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetRowHeight", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
public override bool SetRowHeight (uint rowPos, double fHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
public override bool SetRowHeight(uint rowPos, double fHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// R o w s
|
// R o w s
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override List<DataValue> GetRowDataValues (uint rowPos, int maxColumns = 0)
|
public override List<DataValue> GetRowValues(uint rowPos, int maxColumns = 0)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
List<DataValue> values = new List<DataValue>();
|
List<DataValue> values = new List<DataValue>();
|
||||||
@@ -492,17 +602,17 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
if (maxColumns > 0 && values.Count >= maxColumns) break;
|
if (maxColumns > 0 && values.Count >= maxColumns) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetRowDataValues", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// C e l l s
|
// C e l l s
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
SaMsXmlElement GetCellElement (uint colPos, uint rowPos)
|
SaMsXmlElement GetCellElement(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
String cellId = GetCellId(colPos,rowPos);
|
String cellId = GetCellId(colPos, rowPos);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SaMsXmlElement rowElement = GetRowElement(rowPos);
|
SaMsXmlElement rowElement = GetRowElement(rowPos);
|
||||||
@@ -512,88 +622,99 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
return cellElement;
|
return cellElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetCellElement", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return new SaMsXmlElement(null);
|
return new SaMsXmlElement(null);
|
||||||
}
|
}
|
||||||
public override void SetActiveCell (uint colPos, uint rowPos)
|
public override void SetActiveCell(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
// ToDo SetActiveCell.
|
// ToDo SetActiveCell.
|
||||||
SetErrorState("Not supported");
|
SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
private bool IsCellFormula (uint colPos, uint rowPos)
|
private bool IsCellFormula(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
bool bIsFormula = false;
|
bool bIsFormula = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
|
SaMsXmlElement cellElement = GetCellElement(colPos, rowPos);
|
||||||
bIsFormula = !cellElement.GetAttributeValue("f").IsEmpty();
|
bIsFormula = !cellElement.GetAttributeValue("f").IsEmpty();
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("IsCellFormula", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return bIsFormula;
|
return bIsFormula;
|
||||||
}
|
}
|
||||||
private bool IsCellNumeric (uint colPos, uint rowPos)
|
private bool IsCellNumeric(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
|
SaMsXmlElement cellElement = GetCellElement(colPos, rowPos);
|
||||||
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
||||||
return IsCellNumeric(cellElement, cellStyle);
|
return IsCellNumeric(cellElement, cellStyle);
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("IsCellNumeric", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private bool IsCellNumeric (SaMsXmlElement cellElement)
|
private bool IsCellNumeric(SaMsXmlElement cellElement)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
||||||
return IsCellNumeric(cellElement, cellStyle);
|
return IsCellNumeric(cellElement, cellStyle);
|
||||||
}
|
}
|
||||||
private bool IsCellNumeric (SaMsXmlElement cellElement, SaMsExcelStyle cellStyle)
|
private bool IsCellNumeric(SaMsXmlElement cellElement, SaMsExcelStyle cellStyle)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
return (cellElement.GetAttributeValue("t").IsEmpty() && !IsDateTimeStyle(cellStyle.NumFmtCode));
|
return (cellElement.GetAttributeValue("t").IsEmpty() && !IsDateTimeStyle(cellStyle.NumFmtCode));
|
||||||
}
|
}
|
||||||
private bool IsCellDate (uint colPos, uint rowPos)
|
private bool IsCellDate(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
bool bIsDate = false;
|
bool bIsDate = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
|
SaMsXmlElement cellElement = GetCellElement(colPos, rowPos);
|
||||||
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
SaMsExcelStyle cellStyle = GetCellStyle(cellElement);
|
||||||
return IsCellDate(cellElement, cellStyle);
|
return IsCellDate(cellElement, cellStyle);
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("IsCellDate", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return bIsDate;
|
return bIsDate;
|
||||||
}
|
}
|
||||||
private bool IsCellDate (SaMsXmlElement cellElement)
|
private bool IsCellDate(SaMsXmlElement cellElement)
|
||||||
{
|
{
|
||||||
return IsCellDate(cellElement, GetCellStyle(cellElement));
|
return IsCellDate(cellElement, GetCellStyle(cellElement));
|
||||||
}
|
}
|
||||||
private bool IsCellDate (SaMsXmlElement cellElement, SaMsExcelStyle cellStyle)
|
private bool IsCellDate(SaMsXmlElement cellElement, SaMsExcelStyle cellStyle)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
return IsDateTimeStyle(cellStyle.NumFmtCode);
|
return IsDateTimeStyle(cellStyle.NumFmtCode);
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override String GetCellFormula (uint colPos, uint rowPos)
|
public override String GetCellFormula(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SaMsXmlElement cellElement = GetCellElement(colPos,rowPos);
|
SaMsXmlElement cellElement = GetCellElement(colPos, rowPos);
|
||||||
String formula = cellElement.GetAttributeValue("f");
|
String formula = cellElement.GetAttributeValue("f");
|
||||||
if (formula.IsEmpty())
|
if (formula.IsEmpty())
|
||||||
formula = GetCellText(cellElement, true);
|
formula = GetCellText(cellElement, true);
|
||||||
return formula;
|
return formula;
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetCellFormula", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
private String GetCellText (SaMsXmlElement cellElement, bool trimValue = true)
|
public override String GetCellText(uint colPos, uint rowPos, bool trimWhitespace = true)
|
||||||
|
{
|
||||||
|
ClearErrorState();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SaMsXmlElement cellElement = GetCellElement(colPos, rowPos);
|
||||||
|
return GetCellText(cellElement, true);
|
||||||
|
}
|
||||||
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
private String GetCellText(SaMsXmlElement cellElement, bool trimValue = true)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
String value = "";
|
String value = "";
|
||||||
@@ -605,14 +726,14 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
value = cellElement.GetChildText("v");
|
value = cellElement.GetChildText("v");
|
||||||
if (trimValue) value.TrimAll();
|
if (trimValue) value.TrimAll();
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetCellText", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
public override DataValue GetCellDataValue (uint colPos, uint rowPos)
|
public override DataValue GetCellValue(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
return GetCellDataValue(GetCellElement(colPos, rowPos), false);
|
return GetCellDataValue(GetCellElement(colPos, rowPos), false);
|
||||||
}
|
}
|
||||||
private DataValue GetCellDataValue (SaMsXmlElement cellElement, bool trimTextValue = true)
|
private DataValue GetCellDataValue(SaMsXmlElement cellElement, bool trimTextValue = true)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
@@ -645,12 +766,12 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
return new DataValue(value);
|
return new DataValue(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetCellDataValue", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return new DataValue();
|
return new DataValue();
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Shared string for cell.
|
// Shared string for cell.
|
||||||
private String GetSharedString (SaMsXmlElement nodeElement)
|
private String GetSharedString(SaMsXmlElement nodeElement)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
@@ -658,10 +779,10 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
SaMsXmlElement sharedStringElement = GetSharedStringElement(nodeElement);
|
SaMsXmlElement sharedStringElement = GetSharedStringElement(nodeElement);
|
||||||
return sharedStringElement.GetChildText("t");
|
return sharedStringElement.GetChildText("t");
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetSharedString", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
private SaMsXmlElement GetSharedStringElement (SaMsXmlElement cellElement)
|
private SaMsXmlElement GetSharedStringElement(SaMsXmlElement cellElement)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
if (workbook.SharedStringsDoc == null || cellElement == null || !cellElement.Valid) return null;
|
if (workbook.SharedStringsDoc == null || cellElement == null || !cellElement.Valid) return null;
|
||||||
@@ -678,31 +799,23 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
return siElement;
|
return siElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetSharedStringNode", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return new SaMsXmlElement(null);
|
return new SaMsXmlElement(null);
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override bool SetCellFormula (uint colPos, uint rowPos, String value)
|
public override bool SetCellFormula(uint colPos, uint rowPos, String value, SaMsExcelStyleAttr attr)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
public override bool SetCellFormula (uint colPos, uint rowPos, String value, SaMsExcelItemAttr attr)
|
public override bool SetCellValue(uint colPos, uint rowPos, DataValue value, SaMsExcelStyleAttr attr)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
|
||||||
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
|
// C e l l S t y l e
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
private String GetBuiltInStyleFormat (int numFmtId)
|
private String GetBuiltInStyleFormat(int numFmtId)
|
||||||
{
|
{
|
||||||
// Ref. http://stackoverflow.com/questions/4730152/what-indicates-an-office-open-xml-cell-contains-a-date-time-value
|
// Ref. http://stackoverflow.com/questions/4730152/what-indicates-an-office-open-xml-cell-contains-a-date-time-value
|
||||||
switch (numFmtId)
|
switch (numFmtId)
|
||||||
@@ -758,7 +871,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
private SaMsExcelStyle GetCellStyle (SaMsXmlElement cellElement)
|
private SaMsExcelStyle GetCellStyle(SaMsXmlElement cellElement)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
SaMsExcelStyle style = new SaMsExcelStyle();
|
SaMsExcelStyle style = new SaMsExcelStyle();
|
||||||
@@ -845,10 +958,10 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetStyleNode", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
private bool IsDateStyle (String numFormat)
|
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
|
// 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 (IsTimeStyle(numFormat)) return false;
|
||||||
@@ -857,7 +970,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
if (numFormat.Contains("y")) return true;
|
if (numFormat.Contains("y")) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private bool IsTimeStyle (String numFormat)
|
private bool IsTimeStyle(String numFormat)
|
||||||
{
|
{
|
||||||
if (numFormat.Contains("h")) return true;
|
if (numFormat.Contains("h")) return true;
|
||||||
if (numFormat.Contains(":mm")) return true;
|
if (numFormat.Contains(":mm")) return true;
|
||||||
@@ -865,41 +978,41 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
if (numFormat.Contains(":ss")) return true;
|
if (numFormat.Contains(":ss")) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private bool IsDateTimeStyle (String numFormat)
|
private bool IsDateTimeStyle(String numFormat)
|
||||||
{
|
{
|
||||||
return (IsDateStyle(numFormat) || IsTimeStyle(numFormat));
|
return (IsDateStyle(numFormat) || IsTimeStyle(numFormat));
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Cell attributes.
|
// Cell attributes.
|
||||||
public override bool SetRangeAttr (SaMsExcelRange range, SaMsExcelItemAttr attr)
|
public override bool SetRangeAttr(SaMsExcelRange range, SaMsExcelStyleAttr attr)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Add image to sheet.
|
// Add image to sheet.
|
||||||
public override bool InsertImage (SaMsExcelImage_Config imageConfig)
|
public override bool InsertImage(SaMsExcelImage_Config imageConfig)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override bool FreezePanes (uint colPos, uint rowPos)
|
public override bool FreezePanes(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override bool AutoFit (SaMsExcelRange range)
|
public override bool AutoFitRows(SaMsExcelRange range)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override bool SelectRange (SaMsExcelRange range)
|
public override bool SelectRange(SaMsExcelRange range)
|
||||||
{
|
{
|
||||||
return SetErrorState("Not supported");
|
return SetErrorState(SysUtil.Fn + " " + Msg_NotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
using System;
|
using DocumentFormat.OpenXml;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DocumentFormat.OpenXml;
|
|
||||||
using DocumentFormat.OpenXml.Packaging;
|
using DocumentFormat.OpenXml.Packaging;
|
||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
using Sarand.Net.Standard.Base.App;
|
using Sarand.Net.Standard.Base.App;
|
||||||
using Sarand.Net.Standard.Base.Core;
|
using Sarand.Net.Standard.Base.Core;
|
||||||
using Sarand.Net.Standard.Base.Utils;
|
using Sarand.Net.Standard.Base.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Sarand.Net.Standard.Proc.Excel
|
namespace Sarand.Net.Standard.Proc.Excel
|
||||||
{
|
{
|
||||||
@@ -118,6 +116,10 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
catch (Exception exc) { SaLogger.Warn(exc.GetType().Name + ".OpenWorkbook " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
catch (Exception exc) { SaLogger.Warn(exc.GetType().Name + ".OpenWorkbook " + ExceptionUtil.GetErrorStateMessage(exc)); }
|
||||||
return (workbook != null);
|
return (workbook != null);
|
||||||
}
|
}
|
||||||
|
public override bool CleanseWorkbook()
|
||||||
|
{
|
||||||
|
throw new NotSupportedException(SysUtil.Fn);
|
||||||
|
}
|
||||||
public override bool SaveDocument(String filePath, int fileFormat, bool bAutomaticallyOverwrite)
|
public override bool SaveDocument(String filePath, int fileFormat, bool bAutomaticallyOverwrite)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
@@ -156,13 +158,22 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
/// <summary>Extract the document as a byte array.</summary>
|
||||||
// W o r k s h e e t
|
/// <returns>Document data as byte array.</returns>
|
||||||
//-------------------------------------------------------------------
|
public override byte[] GetDocumentData()
|
||||||
public override bool IsWorksheetValid()
|
|
||||||
{
|
{
|
||||||
return (worksheet != null);
|
throw new NotSupportedException(SysUtil.Fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default style.
|
||||||
|
public override void ApplyDefaultStyle(SaMsExcelStyleAttr attr)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException(SysUtil.Fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// W o r k s h e e t s
|
||||||
|
//-------------------------------------------------------------------
|
||||||
public override uint WorksheetCount
|
public override uint WorksheetCount
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -187,6 +198,11 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
else SetErrorState("SetWorksheetCount - Requested number of worksheets (" + worksheetCount.ToString() + ") must be between 1 and 10");
|
else SetErrorState("SetWorksheetCount - Requested number of worksheets (" + worksheetCount.ToString() + ") must be between 1 and 10");
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override List<String> WorksheetNames { get { return new List<String>(); } }
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
public override bool AddWorksheet(String sheetName)
|
public override bool AddWorksheet(String sheetName)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
@@ -214,6 +230,8 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
|
|
||||||
return (worksheet != null);
|
return (worksheet != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
public override bool RemoveWorksheet(uint worksheetPos)
|
public override bool RemoveWorksheet(uint worksheetPos)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
@@ -243,9 +261,12 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// W o r k s h e e t
|
||||||
|
//-------------------------------------------------------------------
|
||||||
public override bool OpenWorksheet(uint worksheetPos)
|
public override bool OpenWorksheet(uint worksheetPos)
|
||||||
{
|
{
|
||||||
String fn = GetType().Name + ".OpenWorksheet";
|
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
CloseWorksheet();
|
CloseWorksheet();
|
||||||
|
|
||||||
@@ -267,31 +288,49 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
if (worksheetPart != null && sheet != null)
|
if (worksheetPart != null && sheet != null)
|
||||||
worksheet = new WorksheetData(worksheetPos, worksheetPart, sheet);
|
worksheet = new WorksheetData(worksheetPos, worksheetPart, sheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (worksheet != null)
|
if (worksheet != null)
|
||||||
{
|
{
|
||||||
SaLogger.Warn(fn + " Failed to open worksheet " + worksheetPos);
|
SaLogger.Warn(SysUtil.Fn + " Failed to open worksheet " + worksheetPos);
|
||||||
SetErrorState("Failed to open worksheet " + worksheetPos);
|
SetErrorState("Failed to open worksheet " + worksheetPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (worksheet != null);
|
return (worksheet != null);
|
||||||
}
|
}
|
||||||
public override uint WorksheetPos { get { return activeWorksheetPos; } }
|
|
||||||
public override String WorksheetName
|
public override bool OpenWorksheet(String name)
|
||||||
{
|
|
||||||
get { return worksheet.Sheet.Name; }
|
|
||||||
set { worksheet.Sheet.Name = StringUtil.Left(value, 31); }
|
|
||||||
}
|
|
||||||
public override bool SetWorksheetAttr(SaMsExcelItemAttr attr)
|
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
CloseWorksheet();
|
||||||
|
name = StringUtil.TrimWhitespace(name);
|
||||||
|
|
||||||
|
// Extract Sheet by position.
|
||||||
|
uint worksheetPos = 0;
|
||||||
|
Sheet sheet = null;
|
||||||
|
foreach (Sheet sheetCandidate in Sheets)
|
||||||
{
|
{
|
||||||
// ToDo OpenXml SetWorksheetAttr
|
++worksheetPos;
|
||||||
|
if (StringUtil.TrimWhitespace(sheetCandidate.Name).EqualsCI(name))
|
||||||
|
{
|
||||||
|
sheet = sheetCandidate;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("SetWorksheetAttr", exc); }
|
|
||||||
return !HasErrorState();
|
|
||||||
}
|
}
|
||||||
|
if (sheet != null)
|
||||||
|
{
|
||||||
|
WorksheetPart worksheetPart = (WorksheetPart)(WorkbookPart.GetPartById(sheet.Id));
|
||||||
|
|
||||||
|
if (worksheetPart != null && sheet != null)
|
||||||
|
worksheet = new WorksheetData(worksheetPos, worksheetPart, sheet);
|
||||||
|
}
|
||||||
|
if (worksheet != null)
|
||||||
|
{
|
||||||
|
String msg = "Failed to open worksheet: " + name;
|
||||||
|
SetErrorState(msg);
|
||||||
|
SaLogger.Warn(SysUtil.Fn + " " + msg);
|
||||||
|
}
|
||||||
|
return (worksheet != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
public override bool CloseWorksheet()
|
public override bool CloseWorksheet()
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
@@ -303,12 +342,38 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
worksheet = null;
|
worksheet = null;
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("CloseWorksheet", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
worksheet = null;
|
worksheet = null;
|
||||||
activeWorksheetPos = 0;
|
activeWorksheetPos = 0;
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override bool IsWorksheetValid()
|
||||||
|
{
|
||||||
|
return (worksheet != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override uint WorksheetPos { get { return activeWorksheetPos; } }
|
||||||
|
public override String WorksheetName
|
||||||
|
{
|
||||||
|
get { return worksheet.Sheet.Name; }
|
||||||
|
set { worksheet.Sheet.Name = StringUtil.Left(value, 31); }
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override bool SetWorksheetAttr(SaMsExcelStyleAttr attr)
|
||||||
|
{
|
||||||
|
ClearErrorState();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// ToDo OpenXml SetWorksheetAttr
|
||||||
|
}
|
||||||
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
|
return !HasErrorState();
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Worksheet Page Setup.
|
// Worksheet Page Setup.
|
||||||
public override bool SetPageSetup(SaMsExcelPageSetup_Config pageSetupConfig)
|
public override bool SetPageSetup(SaMsExcelPageSetup_Config pageSetupConfig)
|
||||||
@@ -428,7 +493,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("SetPageSetup", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
public override bool SetPageBreak(uint colPos, uint rowPos)
|
public override bool SetPageBreak(uint colPos, uint rowPos)
|
||||||
@@ -445,7 +510,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
worksheet.VPageBreaks.Add(range);
|
worksheet.VPageBreaks.Add(range);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("SetPageSetup", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,7 +524,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// C o l u m n s
|
// C o l u m n s
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
private Column GetColumnByPos (uint columnPos)
|
private Column GetColumnByPos(uint columnPos)
|
||||||
{
|
{
|
||||||
if (worksheet.ActiveColumnPos != columnPos)
|
if (worksheet.ActiveColumnPos != columnPos)
|
||||||
{
|
{
|
||||||
@@ -468,16 +533,19 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
}
|
}
|
||||||
return worksheet.ActiveColumn;
|
return worksheet.ActiveColumn;
|
||||||
}
|
}
|
||||||
public override uint GetActiveColPos()
|
public override uint ActiveColPos
|
||||||
|
{
|
||||||
|
get
|
||||||
{
|
{
|
||||||
if (worksheet == null) return 0;
|
if (worksheet == null) return 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return worksheet.ActiveColumnPos;
|
return worksheet.ActiveColumnPos;
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetActiveCol", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public override double GetColWidth(uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
public override double GetColWidth(uint colPos, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||||
{
|
{
|
||||||
double columnWidth = 0.0;
|
double columnWidth = 0.0;
|
||||||
@@ -485,7 +553,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
// ToDo OpenXML GetColWidth.
|
// ToDo OpenXML GetColWidth.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetColWidth", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return columnWidth;
|
return columnWidth;
|
||||||
}
|
}
|
||||||
public override bool SetColWidth(uint colPos, double columnWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
public override bool SetColWidth(uint colPos, double columnWidth, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||||
@@ -495,23 +563,30 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
// ToDo OpenXML SetColWidth.
|
// ToDo OpenXML SetColWidth.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("SetColWidth", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// R o w s
|
// R o w s
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override uint GetActiveRowPos()
|
public override uint FirstRowPos { get { return (uint)(0); } }
|
||||||
|
public override uint LastRowPos { get { return (uint)(0); } }
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override uint ActiveRowPos
|
||||||
|
{
|
||||||
|
get
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// ToDo OpenXML GetActiveRowPos.
|
// ToDo OpenXML GetActiveRowPos.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetActiveRowPos", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
public override List<DataValue> GetRowDataValues(uint rowPos, int maxColumns = 0)
|
}
|
||||||
|
public override List<DataValue> GetRowValues(uint rowPos, int maxColumns = 0)
|
||||||
{
|
{
|
||||||
List<DataValue> values = new List<DataValue>();
|
List<DataValue> values = new List<DataValue>();
|
||||||
return values;
|
return values;
|
||||||
@@ -523,7 +598,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
// ToDo OpenXML GetRowHeight.
|
// ToDo OpenXML GetRowHeight.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("GetRowHeight", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return rowHeight;
|
return rowHeight;
|
||||||
}
|
}
|
||||||
public override bool SetRowHeight(uint rowPos, double rowHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
public override bool SetRowHeight(uint rowPos, double rowHeight, SaExcelLogicalUnit unit = SaExcelLogicalUnit.Point)
|
||||||
@@ -533,7 +608,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
// ToDo OpenXML SetRowHeight.
|
// ToDo OpenXML SetRowHeight.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("SetRowHeight", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,52 +624,50 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
// ToDo OpenXML GetCellFormula.
|
// ToDo OpenXML GetCellFormula.
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
public override DataValue GetCellDataValue(uint colPos, uint rowPos)
|
public override String GetCellText(uint colPos, uint rowPos, bool trimWhitespace = true)
|
||||||
|
{
|
||||||
|
// ToDo OpenXML GetCellText.
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
public override DataValue GetCellValue(uint colPos, uint rowPos)
|
||||||
{
|
{
|
||||||
// ToDo OpenXML GetCellDataValue.
|
// ToDo OpenXML GetCellDataValue.
|
||||||
return new DataValue();
|
return new DataValue();
|
||||||
}
|
}
|
||||||
public override bool SetCellFormula(uint colPos, uint rowPos, String value)
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
public override bool SetCellFormula(uint colPos, uint rowPos, String value, SaMsExcelStyleAttr attr)
|
||||||
{
|
{
|
||||||
// ToDo OpenXML SetCellFormula.
|
// ToDo OpenXML SetCellFormula.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public override bool SetCellFormula(uint colPos, uint rowPos, String value, SaMsExcelItemAttr attr)
|
|
||||||
|
public override bool SetCellValue(uint colPos, uint rowPos, DataValue value, SaMsExcelStyleAttr attr)
|
||||||
{
|
{
|
||||||
// ToDo OpenXML SetCellFormula.
|
// ToDo OpenXML SetCellValue.
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public override bool SetRowFormulas(uint colPosStart, uint rowPos, List<Object> values)
|
|
||||||
{
|
|
||||||
// ToDo OpenXML SetRowFormulas.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public override bool SetRangeFormulas(SaMsExcelRange range, List<Object> values)
|
|
||||||
{
|
|
||||||
// ToDo OpenXML SetRangeFormulas.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
// Cell attributes.
|
// Cell attributes.
|
||||||
public override bool SetRangeAttr(SaMsExcelRange range, SaMsExcelItemAttr attr)
|
public override bool SetRangeAttr(SaMsExcelRange range, SaMsExcelStyleAttr attr)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// ToDo OpenXML SetRangeAttr.
|
// ToDo OpenXML SetRangeAttr.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("SetRangeAttr", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
private bool SetRangeAttr(Range oRange, SaMsExcelItemAttr attr)
|
private bool SetRangeAttr(Range oRange, SaMsExcelStyleAttr attr)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// ToDo OpenXML SetRangeAttr.
|
// ToDo OpenXML SetRangeAttr.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("SetRangeAttr", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,7 +683,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
// ToDo OpenXML InsertImage.
|
// ToDo OpenXML InsertImage.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("InsertImage", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,19 +695,19 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
// ToDo OpenXML FreezePanes.
|
// ToDo OpenXML FreezePanes.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("FreezePanes", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
public override bool AutoFit(SaMsExcelRange range)
|
public override bool AutoFitRows(SaMsExcelRange range)
|
||||||
{
|
{
|
||||||
ClearErrorState();
|
ClearErrorState();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// ToDo OpenXML AutoFit.
|
// ToDo OpenXML AutoFit.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("AutoFit", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,7 +719,7 @@ namespace Sarand.Net.Standard.Proc.Excel
|
|||||||
{
|
{
|
||||||
// ToDo OpenXML SelectRange.
|
// ToDo OpenXML SelectRange.
|
||||||
}
|
}
|
||||||
catch (Exception exc) { HandleException("SelectRange", exc); }
|
catch (Exception exc) { HandleException(SysUtil.Fn, exc); }
|
||||||
return !HasErrorState();
|
return !HasErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -43,22 +43,6 @@ namespace Sarand.Net.Standard.Proc.Procs
|
|||||||
// Utilities.
|
// 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,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DocumentFormat.OpenXml" Version="2.12.3" />
|
<PackageReference Include="DocumentFormat.OpenXml" Version="2.12.3" />
|
||||||
<PackageReference Include="NPOI" Version="2.5.3" />
|
<PackageReference Include="NPOI" Version="2.6.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user