Modifying pdf metadata using VB.NET - vb.net

Below is the code I am using to modify pdf metadata. The code works fine but I have one issue - instead of modifying the source file, it creates a new file in a different directory. My question is - is there a way to modify source document instead of creating a new document with necessary changes?
If File.Exists(strSource) Then
Dim pdfFileReader As New PdfReader(strSource)
psStamp = New PdfStamper(pdfFileReader, New FileStream(strDest, FileMode.Create))
Dim inf As New SortedDictionary(Of String, String)(StringComparer.Ordinal)
inf.Add("Title", "Modifying metadata")
inf.Add("Company", "My Company")
inf.Add("Author", "myself")
psStamp.MoreInfo = inf
psStamp.Close()
End If
I have tried modifying the line below:
psStamp = New PdfStamper(pdfFileReader, New FileStream(strDest, FileMode.Create))
to point to the source file but then I get an error because file is in use.
Can anyone help?
I'd like to modify the current document without creating a new one. One way to do that would be create a new doc in a different directory, then delete the source doc and then save the newly created doc with the old doc's name but I wanted to see if there is a more elegant solution. Would appreciate any help

Related

VB.NET Save XMLdocument as UTF-8 with BOM

I have written a test application to modify a few hundred XMLs, basically I modify a few nodes and then save the XML again.
The input XML files are UTF-8-BOM but the output is UTF-8 (as viewed in Notepad++).
The code runs on a console application in VB.NET 4.7.2 and this is my basic code:
Dim myXML As XmlDocument = New XmlDocument
Dim nodelist As XmlNodeList
Dim node As XmlNode
myXML.Load(file)
nodelist = myXML.SelectNodes("//root/row")
For Each node In nodelist
'All my code goes here
Next
myXML.Save(file)
I tried things like:
myXML.CreateXmlDeclaration("1.0", "UTF-16", "")
But that didn't work. I have been searching and it seems everyone has the exact oposite issue and checking in the MSDOC I can't see any reference to specify BOM or not:
https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldeclaration.encoding?view=netframework-4.7
The issue is that when the files are imported to the DB without BOM some characters show corruption so I really need the same encoding.
After so much reading I could try to rewrite my app using StreamWriter instead XMLDocument but if there is a workaround about that I would pretty much prefer it :). Thanks!
As suggested by #JosefZ I used this strategy:
Using writer = New XmlTextWriter(file, New UTF8Encoding(True))
Dim xmlsettings As XmlWriterSettings = New XmlWriterSettings
xmlsettings.OmitXmlDeclaration = False
xmlsettings.ConformanceLevel = ConformanceLevel.Fragment
xmlsettings = writer.Settings
myXML.Save(writer)
End Using

how to read a CSV file as resource using TextFieldParser

I have a CSV file in my project resources which I want to read using FileIO.TextFieldParser
I tried Dim parser = new TextFieldParser(My.Resources.ArticlesCSV), but since TextFieldParser expects either a path (as string) or a stream, this is not working.
I guess one possibility is to convert the resource to a stream, but I cannot find how to do that...
What is the best way to get this working?
You can create a new instance of IO.StringReader which is of type TextReader that TextFieldParser will accept. Just pass your CSV file (Thanks to AndrewMorton)
Using strReader As New IO.StringReader(My.Resources.ArticlesCSV)
Using textparser As New TextFieldParser(strReader)
textparser.Delimiters = {","}
While Not textparser.EndOfData
Dim curRow = textparser.ReadFields()
' Do stuff
End While
End Using
End Using

Add a table to a PDF template using iTextSharp and VB.net

I've been stuck on this far longer than I care to admit. I'm trying to use iTextSharp to build a table that I can then insert into a PDF template (which is really just a PDF with a header and an acrofield that needs to be populated). I've currently got code that follows the same outline below:
Dim doc As New Document
Dim reader As PdfReader
Dim stamper As PdfStamper
Dim filestream As FileStream
Dim tempfile As String = My.Computer.FileSystem.GetTempFileName
filestream = New FileStream(tempfile, FileMode.Create)
PdfWriter.GetInstance(doc, filestream)
doc.Open()
generateTableForPdf(listOfData, numColumns, doc)
doc.Close()
reader = New PdfReader(pdfTemplatePath)
stamper = New PdfStamper(reader, filestream)
stamper.AcroFields.SetField("topmostSubform[0].Page1[0].headerField", "some text to go in the field")
The pdfTemplatePath is a private const that has the template's file path that I am trying to use and generateTableForPdf simply creates a dynamically sized table and puts it in doc (doc is passed by ref). I know the table is created because it displays when the page loads, however, the header in the template doesn't appear. I've looked around and found a couple of examples that use byte streams or memory streams, but my attempts at implementing those methods have failed more dramatically. Any help or guidance in better understanding how to go about this is greatly appreciated.

Deserializing in VB Without Failing When the File Does Not Exist

I've nicked some code from msdn to write and read to an xml file to persist my data, but I need a little help with it. I have a dynamic array called darr. As I understand it, I use this code to store it in an xml file:
Dim objStreamWriter As New StreamWriter("C:\temp\test.xml")
Dim x As New XmlSerializer(darr.GetType)
x.Serialize(objStreamWriter, darr)
objStreamWriter.Close()
And this to read it:
Dim objStreamReader As New StreamReader("C:\temp\test.xml")
darr = x.Deserialize(objStreamReader)
objStreamReader.Close()
The thing is, I want the app to read from the file on startup, which means the second block gets called first and if the file doesn't exit yet, it throws an exception. (The first block automatically creates the file if not found.) So two questions:
Is there a way to have the app create the file automatically the first time it runs?
Since the file will be empty... will the code work? If not, is there a workaround? (Okay that's three questions!)
If Not File.Exists("C:\temp\test.xml") Then
' Create the file.
Dim file As System.IO.FileStream
file = System.IO.File.Create("C:\temp\test.xml")
Else
Dim objStreamWriter As New StreamWriter("C:\temp\test.xml")
Dim x As New XmlSerializer(darr.GetType)
x.Serialize(objStreamWriter, darr)
objStreamWriter.Close()
End If

Stream Reader and Writer Conflict

I am making a class that is to help with saving some strings to a local text file (I want to append them to that file and not overwrite so that it is a log file). When I write with the streamwriter to find the end of the previous text, I get an error "the file is not available as it is being used by another process". I looked into this problem on MSDN and I got very little help. I tried to eliminate some variables so I removed the streamreader to check was that the problem and it was. When I tried to write to the file then it worked and I got no error so this made me come to the conclusion that the problem arose in the streamreader. But I could not figure out why?
Here is the code:
Public Sub SaveFile(ByVal Task As String, ByVal Difficulty As Integer, ByVal Time_Taken As String)
Dim SW As String = "C:/Program Files/Business Elements/Dashboard System Files/UserWorkEthic.txt"
Dim i As Integer
Dim aryText(3) As String
aryText(0) = Task
aryText(1) = Difficulty
aryText(2) = Time_Taken
Dim objWriter As System.IO.StreamWriter = New System.IO.StreamWriter(SW, True)
Dim reader As System.IO.StreamReader = New System.IO.StreamReader(SW, True)
reader.ReadToEnd()
reader.EndOfStream.ToString()
For i = 0 To 3
objWriter.WriteLine(aryText(reader.EndOfStream + i))
Next
reader.Close()
objWriter.Close()
End Sub
As Joel has commented on the previous answer it is possible to change the type of locking.
Otherwise building on what Neil has suggested, if to try to write to a file with a new reader it is difficult not to lose the information already within the file.
I would suggest you rename the original file to a temporary name, "UserWorkEthicTEMP.txt" for example. Create a new text file with the original name. Now; read a line, write a line, between the two files, before adding your new data onto the end. Finally Delete the temporary file and you will have the new file with the new details. If you have an error the temporary file will serve as a backup of the original. Some sample code below:
Change file names
Dim Line as string
line=Reader.readline
Do until Line=nothing
objwriter.writeline(line)
line=reader.readline
loop
add new values on the end and remove old file
You are trying to read and write to the same file and this is causing a lock contention. Either store the contents of the file into a variable and then write it back out including your new data to the file.
Psuedo
Reader.Open file
String content = Reader.ReadToEnd()
Reader.Close
Writer.Open file
Loop
Writer.Write newContent
Writer.Close