Converting date string to DateTime (Aspose PDF Library) - string

I'm using the Aspose library within PowerShell and having some issues with the CreationDate values that Aspose is giving me back.
$pdf = New-Object Aspose.Pdf.Facades.PdfFileInfo($pdffile)
$pdf.CreationDate
This returns a string with the value of:
D:20210630133144+10'00'
However PowerShell gives me this error when I try to cast it as DateTime
Cannot convert value "D:20210630133144+10'00'" to type "System.DateTime". Error: "The string was not recognized as a
valid DateTime. There is an unknown word starting at index 0."
I even tried trimming the first 2 chars but then the "+10'00'" timezone at the end causes it to fail as well. I could trim this too, but PowerShell seems to be able to intepret this value as a date automatically when displaying all properties:
PowerShell command line interpreting string as date
I found a similar thread on the Aspose forums where it seems to work as expected in C#. What am I missing here?
EDIT: Output of $pdf | Get-Member
TypeName: Aspose.Pdf.Facades.PdfFileInfo
Name MemberType Definition
---- ---------- ----------
BindPdf Method void BindPdf(Aspose.Pdf.Document srcDoc), void BindPdf(string srcFile), void BindPdf...
ClearInfo Method void ClearInfo()
Close Method void Close(), void IFacade.Close()
Dispose Method void Dispose(), void IDisposable.Dispose()
Equals Method bool Equals(System.Object obj)
GetDocumentPrivilege Method Aspose.Pdf.Facades.DocumentPrivilege GetDocumentPrivilege()
GetHashCode Method int GetHashCode()
GetMetaInfo Method string GetMetaInfo(string name)
GetPageHeight Method float GetPageHeight(int pageNum)
GetPageRotation Method int GetPageRotation(int pageNum)
GetPageWidth Method float GetPageWidth(int pageNum)
GetPageXOffset Method float GetPageXOffset(int pageNum)
GetPageYOffset Method float GetPageYOffset(int pageNum)
GetPdfVersion Method string GetPdfVersion()
GetType Method type GetType()
Save Method void Save(System.IO.Stream destStream), void Save(string destFile), void ISaveableFa...
SaveNewInfo Method bool SaveNewInfo(System.IO.Stream outputStream), bool SaveNewInfo(string outputFile)
SaveNewInfoWithXmp Method bool SaveNewInfoWithXmp(string outputFileName)
SetMetaInfo Method void SetMetaInfo(string name, string value)
ToString Method string ToString()
Author Property string Author {get;set;}
CreationDate Property string CreationDate {get;set;}
Creator Property string Creator {get;set;}
Document Property Aspose.Pdf.Document Document {get;}
HasCollection Property bool HasCollection {get;}
HasEditPassword Property bool HasEditPassword {get;}
HasOpenPassword Property bool HasOpenPassword {get;}
Header Property System.Collections.Generic.Dictionary[string,string] Header {get;set;}
InputFile Property string InputFile {get;set;}
InputStream Property System.IO.Stream InputStream {get;set;}
IsEncrypted Property bool IsEncrypted {get;}
IsPdfFile Property bool IsPdfFile {get;}
Keywords Property string Keywords {get;set;}
ModDate Property string ModDate {get;set;}
NumberOfPages Property int NumberOfPages {get;}
PasswordType Property Aspose.Pdf.PasswordType PasswordType {get;}
Producer Property string Producer {get;}
Subject Property string Subject {get;set;}
Title Property string Title {get;set;}

I personally have never seen this exact DateTime format before, there might be a way to parse it as is but here is an alternative that requires the trimming of D: and the removal of both appearances of ':
$date = "D:20210630133144+10'00'"
[datetime]::ParseExact(
$date.Trim("D:").Replace("'",''),
"yyyyMMddHHmmsszzzz",
[cultureinfo]::InvariantCulture
)
# Results in:
# Wednesday, June 30, 2021 12:31:44 AM

Related

How to read members of a custom VBA class object, passed as a COM__Object, with VB.net? (UIPath)

I have a VBA Function which returns an object of my own class module "CInputDBEntries".
UIPath receives this object as a COM__Object and to read it I need to do some CType Conversion. However no matter how I do it, I can't access the members (values) of the object.
I already tried to convert it to "Object" but can't access the values.
I also tried saving multiple class objects as a Collection but it fails at the CType conversion because it's bugged (VBACollection to Microsoft.VisualBasic.Collection = COM CastTypeException)
I also posted this on the UIPath forums: https://forum.uipath.com/t/invoke-vba-how-to-read-the-retrieved-com-object-in-uipath-vba-function-returns-custom-type/96115
Class Definition:
Private strTitle As String
Private strValue As String
Private boolIntegrity As Boolean
The method:
Public Function ReadRelevantEntries() As CInputDBEntries
Dim entry As CInputDBEntries
entry.Title = "title"
entry.Val = "value"
entry.Integrity = True
Set ReadRelevantEntries = entry
End Function
Currently my conversion is this: CType(listExcelEntries, Object)
Expected result is to be able to pull the values out of the COM__Object so I can read the 2 strings and my bool variable.
Found the solution:
This is the wrong approach
var propertyInfo = comObject.GetType().GetProperty("PropertyName")
This is the correct approach
//get the value of comObject.PropertyName
object propertyValue = comObject.GetType().InvokeMember("PropertyName", System.Reflection.BindingFlags.GetProperty, null, comObject, null);
Credits: https://smehrozalam.wordpress.com/2010/02/16/c-using-reflection-with-com-objects/

How to loop through set values in Object property class in C#?

I have this property class like:
public class ABC{
public string a {get;set;}
public int? b {get;set;}
public string c {get;set;}
public int? d {get;set;}
public int? e {get;set;}
public int? f {get;set;}
}
string lineabc = "8004CF::JAI2310:0:5:0";
string[] splitrow = lineabc.Split(':');
I have to loop through set all the values in this object property class, the values which i want to set in the object class by splitrow array value.
i don't want to set values one by one in class object property like :
ABC.a = splitrow[0];

Map a flat structure to an object with AutoMapper?

The data being returned from a stored procedure has 3 columns of repeating data:
Name | Address | PhoneNumber | UniqueCol1 | UniqueCol2
Ideally I want my model to show that there is repeated data by only storing the values once and have a collection of the unique data.
public class MyViewModel
{
public string Name {get;set;}
public string Address {get;set;}
public string PhoneNumber {get;set;}
public List<MyModel> UniqueData {get;set;}
public class MyModel
{
public string UniqueCol1 {get;set;}
public string UniqueCol2 {get;set;}
}
}
This means I want to map a collection of results to a single object of MyViewModel:
return Mapper.Map<List<StoredProcedureObject>, MyViewModel>(result);
This is where I get my error as I assume I have some configuration that I need to do:
Mapping types:
List`1 -> MyViewModel
Any ideas on the missing step to get this to work?
Automapper is only able to flatten your structure into something simpler. But it's not possible to map a simple class to something more specific.
I would suggest to take only the first entry in your table to fill your base fields like Name, Address, PhoneNumber and iterate over your results to fill your UniqueData List.
I don't see an easier way, because with each possible mapping and without using seperate loops you will get your base data multiple times.
If you don't mind to use another tool, maybe you will have a look at ValueInjecter. I heard you can use this tool for two-way-mappings.

SubSonic How to Execute a SQL Statement?

My site is using Subsonic 2.2 on my site.
I have 1 weird situation where I need to run some ad-hoc SQL statements.
public IList<string> GetDistincList(string TableName, string FieldName)
{
string sqlToRun = string.Format("SELECT DISTINCT {0} FROM {1} ORDER BY {0}", FieldName, TableName);
Query query = new Query(TableName);
query.PleaseRunThis(sqlToRun);
query.ExecuteReader();
}
Can anyone help me here? As it appears, I just want to return a generic list of strings.
Thanks!
Subsonic has a great method called ExecuteTypedList() so you can do somethink like this.
List<int> result = DB.Select(Table.Columns.Id)
.Distinct()
.From<Table>()
.OrderBy(Table.Columns.Id)
.ExecuteTypedList<int>();
or even with pocos:
public class UserResult
{
public int Id {get;set;}
public string Name {get;set;}
}
List<UserResult> users = DB.Select(
User.Columns.UserId + " as Id", // the as ... is only needed if your
User.Columns.UserName + " as Name" // column name differs from the
).From<User>() // property name of your class
.ExecuteTypedList<UserResult>();
Unfortunately this method doesn't work for string since it requires
a) a valuetype
b) a class with a parameterless constructor since the method uses reflection to map the columns from the result to the properties of the class
However I wrote an extension method a while ago that works for string:
Use the Subsonic.Select() ExecuteTypedList Method with String
Look at my own answer in the link.
If you add the extensionmethod to your code you can do:
List<String> result = DB.Select(User.Columns.UserName)
.From<User>()
.ExecuteTypedList();
Use the CodingHorror class.
Here's the SubSonic 3 way of doing it: http://www.subsonicproject.com/docs/CodingHorror
The SubSonic 2 way is similar:
Dim ch As SubSonic.CodingHorror
ch.Execute("delete from #tablename", table)

Parent and Child object in SimpleRepository

How would it work in Subsonic's SimpleReporitory if I wanted to be able to have a 1 to many relationship between objects?
Would I have to create a bridge object and then build my parent object at runtime, or is this support built in?
What I am looking for is the folowing:
Adam's Example Shop...
Public Class Shop
Private m_id As Integer
Private m_Name As String
Private m_Employees As List(Of Employee)
Public Property Id() As Integer
Get
Return m_id
End Get
Set(ByVal value As Integer)
m_id = value
End Set
End Property
Public Property Name() As String
Get
Return m_Name
End Get
Set(ByVal value As String)
m_Name = value
End Set
End Property
Public Property Employees() As List(Of Employee)
Get
Return m_Employees
End Get
Set(ByVal value As List(Of Employee))
m_Employees = value
End Set
End Property
End Class
Public Class Employee
Private m_id As Integer
Private m_Name As String
Public Property Id() As Integer
Get
Return m_id
End Get
Set(ByVal value As Integer)
m_id = value
End Set
End Property
Public Property Name() As String
Get
Return m_Name
End Get
Set(ByVal value As String)
m_Name = value
End Set
End Property
End Class
Main bits:
Dim repo As New SimpleRepository("SubSonicObjectTest", SimpleRepositoryOptions.RunMigrations)
Dim emplyee1 As New Employee
emplyee1.Name = "Martin"
Dim emplyee2 As New Employee
emplyee2.Name = "Adam"
Dim shop As New Shop
shop.Name = "Sub Sonic Store"
shop.Employees = New List(Of Employee)
shop.Employees.Add(emplyee1)
shop.Employees.Add(emplyee2)
repo.Add(Of Shop)(shop)
I think this should create 3 tables:
Shops
Employees
ShopsToEmployees (or some other naming convention)
But I only get a Channels table!
I'm updating the SimpleRepo stuff currently to automatically create joined tables based on collections. Not easy to determine many/many vs 1/many - but I have some ideas :).
To create a one to many relationship you just have to create the object model, SubSonic should do the rest for you e.g.
public class Shop
{
public int Id { get; set; }
public String Name { get; set; }
public List<Employee> Employees { get; set; }
}
public class Employee
{
public int Id { get; set; }
public String Name { get; set; }
}
EDIT: This should generate two tables when you run a migration not 3. The 3 three tables you describe in your question would represent a many to many relationship. Also in your example you're not saving your Employees, SubSonic does not cascade saves so you'll need to save your Shop then add the Employees to it and BatchSave the Employees.

Resources