Need a string value on an Attribute on my HDF5 File - c#

i am trying to add some attributes on my datasets and it is working fine, but i have one problem when writing the value of the attributes, i need them to be a string, not a INT nor float or whatever, every tutorial i find on the internet uses a int value for those attributes..
I've tried a lot of different things and none of them works well and the code is becoming very ugly, this is my code:
foreach (BasicVariable bv in pf.basicVariableList.bvList)
{
H5DataSetId dataSetId = H5D.create(bvGroupId, bv.bvTag, typeId, spaceId);
bv.atribList.Add(new Atribbs("Eng. Unit", "Temperatura"));
bv.atribList.Add(new Atribbs("Atrib2", "Teste"));
foreach(Atribbs a in bv.atribList )
{
H5DataTypeId auxDT = H5T.copy(H5T.H5Type.C_S1);
H5T.setSize(auxDT, H5T.getSize(H5T.H5Type.C_S1));
const int auxData = 2;
long[] auxDim = new long[1];
auxDim[0] = 1;
H5DataSpaceId auxDS = H5S.create_simple(1, auxDim);
var attr_id = H5A.create(dataSetId, a.attName, auxDT, auxDS);
byte[] bytes = Encoding.UTF8.GetBytes(a.valueStr);
var atrData = new string[] { Encoding.Default.GetString(bytes)};
H5A.write<string>(attr_id, auxDT, new H5Array<string>(atrData));
H5A.close(attr_id);
}
H5D.close(dataSetId);
}
H5F.close(fileId);
The attributes i've created are "Eng. Unit" and "Atrib2" and that is working fine, the problem is thet the "Eng. Unit" should have the "Temperatura" value and "Atrib2" should have "Teste" as it's value, this is what i get on the hdfl viewer
enter image description here
enter image description here

Maybe you want to have a look at HDFql, which greatly simplifies how HDF5 files are handled. Here goes a solution using HDFql in C# (assume that the HDF5 file is named test.h5 and the dataset is named dset):
HDFql.Execute("USE FILE test.h5"); // use (i.e. open) HDF5 file "test.h5"
HDFql.Execute("CREATE ATTRIBUTE \"dset/Eng. Unit\" AS VARCHAR VALUES(Temperatura)"); // create attribute "Eng. Unit" in dataset "dset" with an initial value of "Temperatura"
HDFql.Execute("CREATE ATTRIBUTE dset/Atrib2 AS VARCHAR VALUES(Teste)"); // create attribute "Atrib2" in dataset "dset" with an initial value of "Teste"

Related

Setting table parameter in BAPI fails

So, this is my first time doing this and sending an structure to a BAPI that was created by someone else, the BAPI works, Ive tried it in SAP, but now, we need our master system to use it.
This is the structure:
The in values has 3 values...
Ok, so I can connect correctly and get the information, but I am getting an error, and I think this is due to the structure being prepared before being sent...
Here is the code:
public string SendASFEmail(string id, string tipo, string correo)
{
string idCompuesto = "0000" + id;
SAPConnection sapConnection = new SAPConnection();
RfcDestination rfcDes = sapConnection.getRfcDestination(sapConnection);
RfcRepository rfcRep = rfcDes.Repository;
IRfcFunction fun = rfcRep.CreateFunction("ZSLCM_UPDATE_EMAIL");
//Create the structure with id, tipo and correo
IRfcTable tablaEntrada = fun.GetTable("T_CORREOS_IN");
//Assign parameters
RfcStructureMetadata stru = rfcRep.GetStructureMetadata("T_CORREOS_IN");
IRfcStructure datos = stru.CreateStructure();
datos.SetValue("ZFKK_FAM", idCompuesto);
datos.SetValue("BPKI", tipo);
datos.SetValue("SMTP_ADDR", correo);
tablaEntrada.Append(datos);
fun.SetValue("T_CORREOS_IN", tablaEntrada);
// RUN
fun.Invoke(rfcDes);
//Success and get the out table which contains the same parameters plus message in column #4
IRfcTable tablaSalida = fun.GetTable("T_CORREOS_OUT");
DataTable dtMessages = GetDataTableFromRFCTable(tablaSalida); //this is to take the out structure and just get the string
string respuesta = dtMessages.Rows[0][3].ToString();
return respuesta;
}
And I keep getting the error:
Additional information: metadata for StructureOnly T_CORREOS_IN not available: NOT_FOUND: No active nametab exists for T_CORREOS_IN
Your problem is in the statement:
RfcStructureMetadata stru = rfcRep.GetStructureMetadata("T_CORREOS_IN");
API function GetStructureMetadata( ) reads SAP repository (!) structure and not parameters of RFC module, hence is the error.
For filling RFC table you need smth like this:
IRfcFunction fn = repo.CreateFunction("ZSLCM_UPDATE_EMAIL");
var correos = fn.GetTable("T_CORREOS_IN");
foreach (ListViewItem lvi in correos.Items)
{
//Create new correos row
correos.Append();
//Populate current row with data from list
correos.SetValue("ZFFK_FAM", lvi.SubItems[0].Text);
correos.SetValue("BKPI", lvi.SubItems[1].Text);
correos.SetValue("SMTP_ADDR", lvi.SubItems[2].Text);
}
Here is the reference answer also with .Net dataTable type sample.
Read official Help about NCo functions.

How to populate XML object with data, based on XSD

I need to export data into XML file, using XSD. There are many examples how to do it, but most of them do not show how to popuate the actual data, but to save the object as an XML. The one I could find didn't work for me.
1) I use an xsd file of Agresso http://services.agresso.com/schema/ABWInvoice/2011/11/14/ABWInvoice.html
which I have successfully downloaded and generated a class with xsd.exe command.
2) I have added this class to my project. ABWInvoice is the class for the complexType element Invoice. The xml may contain more than one invoice, hence its maxOccurs is set to "unbounded". Each Invoice can have InvoiceNo element and Header complex element.
3) I have started to write the code and first thought I can use a list, as the number of invoices is dynamic. But List<ABWInvoice> list = new ABWInvoice(); didn't work "Cannot implicitly convert type 'abc.Agresso.ABWInvoice' to 'System.Collections.Generic.List'", so I have decided to at least try to have one record and go from there, but oAgresso.Invoice[0].Header fails in runtime with System.NullReferenceException: 'Object reference not set to an instance of an object.'
private void CreateXMLHeader()
{
var oAgresso = new ABWInvoice { };
oAgresso.Invoice[0] = new ABWInvoiceInvoice
{ InvoiceNo = "1" };
oAgresso.Invoice[0].Header = new ABWInvoiceInvoiceHeader()
{
OrderRef = "5678",
InvoiceDate = Date.Now
};
//var agressoXMLImport = Shared.XMLHelper.ReadXml<ABWInvoice>(#"E:\temp\ABW_Invoice_Test.xml");
Shared.XMLHelper.SaveXml<ABWInvoice>(oAgresso, #"e:\temp\ABW_Export_Test.xml");
}
Can you advise on how
1) build a dynamic array (I do not know the amount of invoices, when I start building the XML;
2)What is wrong with my current code?
Much appreciated!
Member arrays need to be initialized with known size, so its easier to make a List of ABWInvoiceInvoice then populate it with your data by using add method and at the end assign whole list to your member array
private void CreateXMLHeader()
{
var oAgresso = new ABWInvoice { };
List<ABWInvoiceInvoice> invlist = new List<ABWInvoiceInvoice>();
invlist.Add(new ABWInvoiceInvoice { InvoiceNo = "1" ,
Header= new ABWInvoiceInvoiceHeader()
{
OrderRef = "5678",
InvoiceDate = DateTime.Now
}
});
oAgresso.Invoice = invlist.ToArray();

How to set Excel "Print Titles" with OpenXML

How can I set the "Print Titles" property of a spreadsheet with OpenXML, to have a row show at the top of every printed page?
The property is directly saved in the SpreadsheetPrintingParts object, however, this doesn't appear to be fully integrated into OpenXML as of yet, and requires passing a base64 string in to the variable. (see here) The content of this string appears to be tied to the machine the file is opened on, which didn't work for my implementation - I wasn't able to create a non-corrupt file through SpreadsheetPrintingParts.FeedData().
Instead, I found this post which stated giving the row the defined name "Print_Titles" has the same effect. I was then able to create a defined name through OpenXML with the following code:
public void SetPrintTitleRows(int startRowIndex, int? endRowIndex = null)
{
var localSheetId = _localsheetId++; //LocalSheetIds are 0-indexed.
var definedName = new DefinedName
{
Name = "_xlnm.Print_Titles",
LocalSheetId = localSheetId,
Text = String.Format("\'{0}\'!${1}:${2}", _sheetName, startRowIndex, endRowIndex ?? startRowIndex)
};
if (_workbookPart.Workbook.DefinedNames == null)
{
var definedNamesCol = new DefinedNames();
_workbookPart.Workbook.Append(definedNamesCol);
}
_workbookPart.Workbook.DefinedNames.Append(definedName);
}
Points to note:
DefinedName.LocalSheetId is zero-indexed, as opposed to Sheet.Id which is 1-indexed
DefinedNames is once per workbook, but can contain multiple DefinedName objects for different sheets.

FileHelpers - Column mapping

Quick question regarding filehelper library:
I have used file helper engine to read stream, do my validation and if the CSV file has not got a header we need to match/map it to my model: i.e
id, name, age, phone, sex,
but the CSV might not come in this format/order all the time and we need to match them using a drop down list for each column.
Is there any way I can do this?
Thannks,
The short answer, no. BUT you can create a dependent class dynamically:
Since you have the list of possible fields in your JSON file, I would recommend doing a basic System.IO ReadLine for the first data row, and then parse by your delimiter for the individual headers. i.e.:
string headerString;
var headers = new List<String>();
var file = new System.IO.StreamReader("C:\\myFile.txt");
headerString = file.ReadLine();
file.Close();
headers = headerString.Split(',').ToList();
now you have the list of strings for the first row to match against your JSON file. Then you can create your dependent class using System.Reflection.Emit (referenced link below)
typeBuilder.SetParent(typeof(MyFileHelperBaseClass));
// can place the property definitions in a for loop against your headers
foreach(string h in headers){
typeBuilder.DefineProperty("<header/col#>", ..., typeof(System.Int32), null);
}
stackoverflow article 14724822: How Can I add properties to a class on runtime in C#?
File Helpers gets a little finicky at times, so it will take some tweaking.
Hope this helps
You can use File.ReadLines(#"C:\myfile.txt").First() to read the first line and get the headers.
Then you can just use a FileHelpers CodeBuilder to build your runtime class. From the example for a delimited csv file:
DelimitedClassBuilder cb = new DelimitedClassBuilder("Customers", ",");
cb.IgnoreFirstLines = 1;
cb.IgnoreEmptyLines = true;
cb.AddField("BirthDate", typeof(DateTime));
cb.LastField.TrimMode = TrimMode.Both;
cb.LastField.FieldNullValue = DateTime.Today;
cb.AddField("Name", typeof(string));
cb.LastField.FieldQuoted = true;
cb.LastField.QuoteChar = '"';
cb.AddField("Age", typeof(int));
engine = new FileHelperEngine(cb.CreateRecordClass());
DataTable dt = engine.ReadFileAsDT("testCustomers.txt");
Then you can traverse the resulting data table.

exporting a comma separated values text file to use in excel

In my C# winforms program I want to make an export function that will create a comma separated text file or csv. I am not sure about the logic of how to do this the best way. My exported file will be like this :
Family Name, First Name, Sex, Age
Dekker, Sean, Male, 23
Doe, John, Male, 40
So the first line I want to be the name of the columns, and the rest should be treated as values. Is it ok in this way for later usage? Or I should not include column names?
Would be nice to hear your experiences about this!
Sean,
sorry don't have enough privilege points to comment directly on your post. I think you may be confusing CSV and Excel files here. A CSV is simply a text file where each value is separated by a comma, there is no special formating etc. Excel will display CSV files since it knows how to open them but you can just as easily open them in notepad.
Excel .xslx files are different and can contain all sorts of different formats, charts etc. To format these files its important to understand that .xslx files are essentially zips. So the first place to start is to create an excel file with some data, save it and then rename the extension to .zip
Open the zip file created now and you will see a number of different folders and files, of these the most important for your purposes is the XL directory. In this folder you will see a shared strings xml file and a worksheets folder.
Lets start by going into the worksheet folder and opening sheet1.xml. Look for the line that says "
If there is text in this column, i.e. data that excel should read as text then you will have something like 0. This indicates that cell A1 is of type string t="s" and that the value is to be found as the first value in the SharedStrings.xml file 0
If there is a number in the cell then you may have something like 234. In this case Excel knows to use the value 234 in this cell.
So in your case you will need to do the following:
1: create the excel document in C# - there are a number of libraries available for this
2: Open the excel file as a zip
3: Modify in your case the styles and worksheets xml files
4: Save the document
That is absolutely fine to do (to state the obvious....). Excel has a little checkbox that allows the user importing to use the first line as column headers if they select it.
I would also suggest that you leave out the spaces at the start of each piece of data, it isn't necessary.
In general its best practice to include the column headers, the only reason not to do so would be an external program over which you have no control accessing your data which doesn't realise that the first row are the column headers and which can't be changed.
To create the export function something like this should work:
private static List<Person> people = new List<Person>();
static void Main(string[] args)
{
// add some people
people.Add(
new Person() { firstName = "John", familyName = "Smith", sex = Sex.Male, age = 12 }
);
people.Add(
new Person() { firstName = "Mary", familyName = "Doe", sex = Sex.Female, age = 25 }
);
// write the data
Write();
}
static void Write()
{
using (TextWriter tw = new StreamWriter(#"c:\junk1\test.csv", false))
{
// write the header
tw.WriteLine("Family Name, First Name, Sex, Age");
// write the details
foreach(Person person in people)
{
tw.WriteLine(String.Format("{0}, {1}, {2}, {3}", person.familyName, person.firstName, person.sex.ToString(), person.age.ToString()));
}
}
}
}
/// <summary>
/// Applicable sexes
/// </summary>
public enum Sex
{
Male,
Female
}
/// <summary>
/// holds details about a person
/// </summary>
public class Person
{
public string familyName { get; set; }
public string firstName { get; set; }
public Sex sex { get; set; }
public int age { get; set; }
}
You can use Dataset to do this.
Please refer here
//Why not save the lines to a List<string> object, first List<sting>Object.Add//("your headers"), use the string.Join("," "your Header Array string[]" do not add //(+",") the .Join extension menthod will handle that for you.
// here is an example
//if you were to retreive the header values from a database using a SQL Reader
var reader = sqlcmdSomeQueryCommand.ExecuteReader();
var columns = new List<string>();
//get all the field names from the Columns var
for (int intCounter = 0; intCounter < reader.FieldCount; intCounter++)
{
columns.Add(reader.GetName(intCounter));
}
strarryTmpString = columns.ToArray();
string TmpFields = string.Join(", ", strarryTmpString);
columns.Clear();
columns.Add(TmpFields);
//you can save the TmpFieldList to later add the rest of your comma delimited fields
write line by line in a foreach loop or use the List<string> object .foreach(delegate(string delString)
{
someStreamWriterObject.WriteLine(delString)
});

Categories

Resources