adding to List (of Byte()) - vb.net

The function requires a generic list (of Byte()) to be passed as agrs and I just cannot seem to get anything to add to this list.I require printdata(0) & (1) adding to it.
Dim printdata(1) As String
labelname = "WasNow"
printdata(0) = "9,99"
printdata(1) = "6.99"
Dim args = New List(Of Byte())
args.Add(Convert.ToByte(printdata))
ApplicationContext.CurrentDevice.Printer.Print(labelname, 1, args)
Frmscanprint.Show()
This is the working C# version of the code with only one item to add.
private void printButton_Click(object sender, EventArgs e)
{
try
{
this.printNumber++;
var args = new List<byte[]>() { Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "Test #{0}", this.printNumber)) };
if (!ApplicationContext.AllDevicesSelected)
{
ApplicationContext.CurrentDevice.Printer.Print("SamplePrint", 1, args);
}
else
{
PrintSampleForEachDevice("SamplePrint", 1, args);
}
}
}

The C# example you provided gets a single string and converts it to a byte array, assigning this array to the newly created list.
Your code is not doing the same thing. You are trying to convert a string array to a byte array. This conversion type is not allowed by the method you are trying to use. Even if it is possible, the result would be a single byte array with the entire content and not an array of byte array.
If you want to do the same thing as the C# code does, you shoud do it for each itm from your string array a time.
If you want to do the same thing as the C# code, you shoud do it for each single item from your string array. For example:
For Each item As String In printdata
args.Add(Encoding.ASCII.GetBytes(item))
Next

Related

Type used in a using statement should be implicitly convertible to IDisposable

I have the following logic:
try
{
using (var contents = new StreamReader(file.InputStream).ReadToEnd())
{
var rows = contents.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
rows.ForEach(r => mids.Add(r.Split(',')[0]));
}
}
catch(IOException e)
{}
finally
{
contents = null;
}
In the using statement I have an error in the question. It happened probably because I use .ReadToEnd() method.
Without the using statement I would need to use try/catch/finally for a clean up (to fix veracode resource clean up issue)
How can I fix that, so I don't need to use try\catch\finally and use only the using statement?
So, using should be used with object which implements IDisposable interface. You calling ReadToEnd method which returns string and contents is not a IDisposable (because string is not).
You should use it like this:
using (var streamReader = new StreamReader(file.InputStream))
{
var contents = streamReader.ReadToEnd();
// Some actions
}
You want to clean up StreamReader, contents will be collected by GC when method will finished because it has type string.

Net.Http.StringContent date format

I'm trying to upload a file with some metadata to a Web API. Everything is fine within the developer environment. But when the same API is hosted in Azure I get the following date parsing error:
Conversion from string "31/03/2019 11:33:52" to type 'Date' is not valid.
I guess StringContent should write the date on ISO 8601 format and it does not.
Next is a simplification of my procedure:
Public Async Function UploadDocFile(oHttpClient as HttpClient, url as string, ByVal oByteArray as Byte(), exs As List(Of Exception)) As Task(Of Boolean)
Dim retval As Boolean
Dim formContent = New Net.Http.MultipartFormDataContent From {
{New Net.Http.StringContent("DateCreated"), now},
{New Net.Http.StreamContent(New IO.MemoryStream(oDocfile.Stream)), "pdf", "pdf.jpg"}
}
Dim response = Await oHttpClient.PostAsync(url, formContent)
If response.StatusCode = 200 Then
retval = True
Else
exs.Add(New Exception(response.ReasonPhrase))
End If
Return retval
End Function
You are using a Collection Initializer to add items to the MultipartFormDataContent; you're expected to follow this overload of the Add method, which accepts two parameters of type HttpContent and String, respectively.
Thus, the second value enclosed in the braces ({}) should be the name of the data content, not its value. On the other hand, the parameter passed to the StringContent constructor should be the value (content), not the name. You basically have them swapped out. If you'd had Option Strict set to On (which is something you should do, BTW), you would've gotten a compiler error and would've easily identified the mistake.
Your code should look something like this:
Dim formContent = New Net.Http.MultipartFormDataContent From
{
{New Net.Http.StringContent(Now.ToString("SomeFormat")), "DateCreated"},
' More values.
}
..where SomeFormat is a format supported by the web API that you're using.

iText LocationTextExtractionStrategy/HorizontalTextExtractionStrategy splits text into single characters

I used a extended version of LocationTextExtractionStrategy to extract connected texts of a pdf and their positions/sizes. I did this by using the locationalResult. This worked well until I tested a pdf containing texts with a different font (ttf). Suddenly these texts are splitted into single characters or small fragments.
For example "Detail" is not any more one object within the locationalResult list but splitted into six items (D, e, t, a, i, l)
I tried using the HorizontalTextExtractionStrategy by making the getLocationalResult method public:
public List<TextChunk> GetLocationalResult()
{
return (List<TextChunk>)locationalResultField.GetValue(this);
}
and using the PdfReaderContentParser to extract the texts:
reader = new PdfReader("some_pdf");
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
var strategy = parser.ProcessContent(i, HorizontalTextExtractionStrategy());
foreach (HorizontalTextExtractionStrategy.HorizontalTextChunk chunk in strategy.GetLocationalResult())
{
// Do something with the chunk
}
but this also returns the same result.
Is there any other way to extract connected texts from a pdf?
I used a extended version of LocationTextExtractionStrategy to extract connected texts of a pdf and their positions/sizes. I did this by using the locationalResult. This worked well until I tested a pdf containing texts with a different font (ttf). Suddenly these texts are splitted into single characters or small fragments.
This problem is due to wrong expectations concerning the contents of the LocationTextExtractionStrategy.locationalResult private list member variable.
This list of TextChunk instances contains the pieces of text as they were forwarded to the strategy from the parsing framework (or probably as they were preprocessed by some filter class), and the framework forwards each single string it encounters in a content stream separately.
Thus, if a seemingly connected word in the content stream actually is drawn using multiple strings, you get multiple TextChunk instances for it.
There actually is some "intelligence" in the method getResultantText joining these chunks properly, adding a space where necessary and so on.
In case of your document, "DETAIL " usually is drawn like this:
[<0027> -0.2<00280037> 0.2<0024002c> 0.2<002f> -0.2<0003>] TJ
As you see there are slight text insertion point moves between 'D' and 'E', 'T' and 'A', 'I' and 'L', and 'L' and ' '. (Such mini moves usually represent kerning.) Thus, you'll get individual TextChunk instances for 'D', 'ET', 'AI', and 'L '.
Admittedly, the LocationTextExtractionStrategy.locationalResult member is not very well documented; but as it is a private member, this IMHO is forgivable.
That this worked well for many documents is due to many PDF creators not applying kerning and simply drawing connected text using single string objects.
The HorizontalTextExtractionStrategy is derived from the LocationTextExtractionStrategy and mainly differs from it in the way it arranges the TextChunk instances to a single string. Thus, you'll see the same fragmentation here.
Is there any other way to extract connected texts from a pdf?
If you want "connected texts" as in "atomic string objects in the content stream", you already have them.
If you want "connected texts" as in "visually connected texts, no matter where the constituent letters are drawn in the content stream", you have to glue those TextChunk instances together like the LocationTextExtractionStrategy and HorizontalTextExtractionStrategy do in getResultantText in combination with the comparison methods in their respective TextChunkLocationDefaultImp and HorizontalTextChunkLocation implementations.
After debugging deep into the iTextSharp library I figured out that my texts are drawn with the TJ operator as mkl also mentioned.
[<0027> -0.2<00280037> 0.2<0024002c> 0.2<002f> -0.2<0003>] TJ
iText processes these texts not as a single PdfString but as an array of PdfObjects which ends up in calling renderListener.RenderText(renderInfo) for each PdfString item in it (see ShowTextArray class and DisplayPdfString method). In the RenderText method however the information about the relation of the pdf strings within the array got lost and every item is added to locationalResult as an independent object.
As my goal is to extract the "argument of a single text drawing instruction" I extended the PdfContentStreamProcessor class about a new method ProcessTexts which returns a list of these atomic strings. My workaround is not very pretty as I had to copy paste some private fields and methods from the original source but it works for me.
class PdfContentStreamProcessorEx : PdfContentStreamProcessor
{
private IDictionary<int, CMapAwareDocumentFont> cachedFonts = new Dictionary<int, CMapAwareDocumentFont>();
private ResourceDictionary resources = new ResourceDictionary();
private CMapAwareDocumentFont font = null;
public PdfContentStreamProcessorEx(IRenderListener renderListener) : base(renderListener)
{
}
public List<string> ProcessTexts(byte[] contentBytes, PdfDictionary resources)
{
this.resources.Push(resources);
var texts = new List<string>();
PRTokeniser tokeniser = new PRTokeniser(new RandomAccessFileOrArray(new RandomAccessSourceFactory().CreateSource(contentBytes)));
PdfContentParser ps = new PdfContentParser(tokeniser);
List<PdfObject> operands = new List<PdfObject>();
while (ps.Parse(operands).Count > 0)
{
PdfLiteral oper = (PdfLiteral)operands[operands.Count - 1];
if ("Tj".Equals(oper.ToString()))
{
texts.Add(getText((PdfString)operands[0]));
}
else if ("TJ".Equals(oper.ToString()))
{
string text = string.Empty;
foreach (PdfObject entryObj in (PdfArray)operands[0])
{
if (entryObj is PdfString)
{
text += getText((PdfString)entryObj);
}
}
texts.Add(text);
}
else if ("Tf".Equals(oper.ToString()))
{
PdfName fontResourceName = (PdfName)operands[0];
float size = ((PdfNumber)operands[1]).FloatValue;
PdfDictionary fontsDictionary = resources.GetAsDict(PdfName.FONT);
CMapAwareDocumentFont _font;
PdfObject fontObject = fontsDictionary.Get(fontResourceName);
if (fontObject is PdfDictionary)
_font = GetFont((PdfDictionary)fontObject);
else
_font = GetFont((PRIndirectReference)fontObject);
font = _font;
}
}
this.resources.Pop();
return texts;
}
string getText(PdfString #in)
{
byte[] bytes = #in.GetBytes();
return font.Decode(bytes, 0, bytes.Length);
}
private CMapAwareDocumentFont GetFont(PRIndirectReference ind)
{
CMapAwareDocumentFont font;
cachedFonts.TryGetValue(ind.Number, out font);
if (font == null)
{
font = new CMapAwareDocumentFont(ind);
cachedFonts[ind.Number] = font;
}
return font;
}
private CMapAwareDocumentFont GetFont(PdfDictionary fontResource)
{
return new CMapAwareDocumentFont(fontResource);
}
private class ResourceDictionary : PdfDictionary
{
private IList<PdfDictionary> resourcesStack = new List<PdfDictionary>();
virtual public void Push(PdfDictionary resources)
{
resourcesStack.Add(resources);
}
virtual public void Pop()
{
resourcesStack.RemoveAt(resourcesStack.Count - 1);
}
public override PdfObject GetDirectObject(PdfName key)
{
for (int i = resourcesStack.Count - 1; i >= 0; i--)
{
PdfDictionary subResource = resourcesStack[i];
if (subResource != null)
{
PdfObject obj = subResource.GetDirectObject(key);
if (obj != null) return obj;
}
}
return base.GetDirectObject(key); // shouldn't be necessary, but just in case we've done something crazy
}
}
}

RESTful API call in SSIS package

As part of a SSIS (2005) package I am calling a RESTful API through a script component (VB.NET). I am getting the records back OK. The problem I have though is processing the format it comes back in so I can output it (split into the separate output columns) within the data flow and write into a SQL table. Don't know where to start - anyone got any ideas? I have no control over the API so am stuck with this format.
Here is the schema as per the API documentation:
{StatusMessage : <string>, Unit : <string> [ { VehicleID : <int>, RegistrationNumber : <string>, DistanceTravelled : <double>} ] }
And here is a sample of the data returned (it comes back as a single line of text):
{"VehicleDistance":
[
{
"VehicleId":508767,
"RegistrationNumber":"BJ63 NYO",
"DistanceTravelled":0.09322560578584671
},
{
"VehicleId":508788,
"RegistrationNumber":"BJ63 NYL",
"DistanceTravelled":6.1591048240661621
},
{
"VehicleId":508977,
"RegistrationNumber":"PE12 LLC",
"DistanceTravelled":60.975761413574219
},
{
"VehicleId":510092,
"RegistrationNumber":"BJ64 FCY",
"DistanceTravelled":14.369173049926758
},
{
"VehicleId":510456,
"RegistrationNumber":"BJ63 NYY",
"DistanceTravelled":4.04599142074585
},
{
"VehicleId":513574,
"RegistrationNumber":"BL64 AEM",
"DistanceTravelled":302.150390625
}
],
"StatusMessage":null,
"Unit":"imperial",
"HttpStatus":200
}
This is Javscript Object Notation AKA JSON and you need to deserialise it. The problem is that using SSIS is tricky with third party tools that are popular (and fast) but VB.Net actually has a built in class to serialise and deserialise JSON called JavaScriptSerializer
First add a Reference to your project called System.Web.Extensions and then you can use the JavaScriptSerializer to deserialise your JSON.
I've put your JSON in a file for easier handling so first I have to...
Dim sJSON As String = ""
Using swReadFile As New System.IO.StreamReader("E:\JSON.txt")
sJSON = swReadFile.ReadToEnd()
End Using
The rest is the pertinent bit, so first add 2 Imports...
Imports System.Collections.Generic
Imports System.Web.Script.Serialization
Then for example we can...
Dim lvSerializer As JavaScriptSerializer = New JavaScriptSerializer()
lvSerializer.MaxJsonLength = 2147483644
Dim dictParsedJSONPairs As Dictionary(Of String, Object) = lvSerializer.Deserialize(Of Dictionary(Of String, Object))(sJSON)
If dictParsedJSONPairs.ContainsKey("VehicleDistance") AndAlso _
TypeOf dictParsedJSONPairs("VehicleDistance") Is ArrayList Then
Dim ArrayEntries As ArrayList = DirectCast(dictParsedJSONPairs("VehicleDistance"), ArrayList)
For Each ArrayEntry As Object In ArrayEntries
Dim DictEntry As Dictionary(Of String, Object) = DirectCast(ArrayEntry, Dictionary(Of String, Object))
If DictEntry.ContainsKey("VehicleId") Then Console.WriteLine("VehichleId:" & DictEntry("VehicleId"))
Next
End If
If dictParsedJSONPairs.ContainsKey("Unit") Then
Console.WriteLine("Unit is " & dictParsedJSONPairs.Item("Unit"))
End If
Clearly you should research JSON before launching into serious use. The object can be nested JSON (i.e. Dictionary(Of String, Object)), a number of some sort, a string or an ArrayList
It could be a bit late but you may want to have a look at json.net from Newtonsoft (website). The component provided contains .Net 2.0 version.
Using it in a SSIS script task is quite simple. I did it in SSIS2008 based on .Net 3.5 to parse JSON string like below. And according to the document, it should work for .Net 2.0 version as well.
//I assume you had obtained JSON in string format
string JasonBuffer;
//define Json object
JObject jObject = JObject.Parse(JasonBuffer);
//In my example the Json object starts with result
JArray Results = (JArray)jObject["result"];
//loop the result
foreach (JObject Result in Results)
{
//for simple object
JObject joCustomer = (JObject)Result["Customer"];
//do something...
//for complex object continue drill down
foreach (JObject joSection in Result["Sections"])
{
foreach (JObject joDepartment in joSection["Departments"])
{
foreach (JObject joItem in joDepartment["Items"])
{
}
You can find some actual code here: link

Using JSON with VB.NET ASP.NET 2.0

Total newby question here, I've been struggling with it for hours!
I'm trying to understand how to actually use, and create JSON data. I've been Googling all afternoon and trying to understand what I fine here http://james.newtonking.com/projects/json/help/ having downloaded the Newtonsoft DLLs.
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("CPU");
jsonWriter.WriteValue("Intel");
jsonWriter.WritePropertyName("PSU");
jsonWriter.WriteValue("500W");
jsonWriter.WritePropertyName("Drives");
jsonWriter.WriteStartArray();
jsonWriter.WriteValue("DVD read/writer");
jsonWriter.WriteComment("(broken)");
jsonWriter.WriteValue("500 gigabyte hard drive");
jsonWriter.WriteValue("200 gigabype hard drive");
jsonWriter.WriteEnd();
jsonWriter.WriteEndObject();
}
Should create something that looks like:
{
"CPU": "Intel",
"PSU": "500W",
"Drives": [
"DVD read/writer"
/*(broken)*/,
"500 gigabyte hard drive",
"200 gigabype hard drive" ]
}
and I am sure it does... but how do I view it? How do I turn that into an object that the browser can output.
It seems to me that the first stage I need to resolve is "how to create" JSON files/strings, next stage will be how to actually use them. If it helps answer the question, what I'm aiming for initially is to be able to use AJAX Autocomplete from a search page generated from my MySQL database, I was hoping I could write a simple SQL query and have that returned using something similar to the above, but I'm clearly going about it all wrong!
BTW, the example above is in C#, I have successfully converted the process to VB, as that's what I am using, but any responses would be much appreciated as VB examples!
I came across this post about two years after it was posted, but I had the exact same question and noticed that the question wasn't really answered. To answer OP's question, this will get you the JSON string in his example.
sb.toString()
The upshot is that you need to get the JSON string back to the browser. You can either place it in a javascript variable (be sure to clean up line enders and single quotes if you do this) or pass it back as the result of an ajax query.
We actually use the built-in Javascript serializer since it has support both on the server and the client side and is quite easy to use. Assuming that you have an existing object, this code goes on the server side:
''' <summary>
''' This method safely serializes an object for JSON by removing all of the special characters (i.e. CRLFs, quotes, etc)
''' </summary>
''' <param name="oObject"></param>
''' <param name="fForScript">Set this to true when the JSON will be embedded directly in web page (as opposed to being passed through an ajax call)</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function SerializeObjectForJSON(ByVal oObject As Object, Optional ByVal fForScript As Boolean = False) As String
If oObject IsNot Nothing Then
Dim sValue As String
sValue = (New System.Web.Script.Serialization.JavaScriptSerializer).Serialize(oObject)
If fForScript Then
' If this serialized object is being placed directly on the page, then we need to ensure that its CRLFs are not interpreted literlally (i.e. as the actual JS values)
' If we don't do this, the script will not deserialize correctly if there are any embedded crlfs.
sValue = sValue.Replace("\r\n", "\\r\\n")
' Fix quote marks
Return CleanString(sValue)
Else
Return sValue
End If
Else
Return String.Empty
End If
End Function
On the client side, deserialization is trivial:
// The result should be a json-serialized record
oRecord = Sys.Serialization.JavaScriptSerializer.deserialize(result.value);
Once you have deserialized the object, you can use its properties directly in javascript:
alert('CPU = ' + oRecord.CPU);
In terms of generating the JSON try
public class HardwareInfo
{
[JsonProperty(PropertyName = "CPU")]
public string Cpu { get; set; }
[JsonProperty(PropertyName = "PSU")]
public string Psu { get; set; }
[JsonProperty]
public ICollection<string> Drives { get; set; }
}
public string SerializeHardwareInfo()
{
var info = new HardwareInfo
{
Cpu = "Intel",
Psu = "500W",
Drives = new List<string> { "DVD read/writer", "500 gigabyte hard drive", "200 gigabype hard drive" }
};
var json = JsonConvert.SerializeObject(info, Formatting.Indented);
// {
// "CPU": "Intel",
// "PSU": "500W",
// "Drives": [
// "DVD read/writer",
// "500 gigabyte hard drive",
// "200 gigabype hard drive"
// ]
// }
return json;
}
The formatting argument is optional. Best of luck.