How can I look for certain words in a file and then do something? - vb.net

How can I look for certain words in a file then do something if any of the words were found?
I would like to do something if for example any of these words banana horse window whatever is found within a file.
Here is my last attempt
Dim thefile As String = "C:\application\thefile"
If File.Exists(thefile) Then
Using reader As New StreamReader(thefile)
While Not reader.EndOfStream
Dim line As String = reader.ReadLine()
If line.Contains("Banana") OrElse line.Contains("horse") OrElse line.Contains("window") OrElse line.Contains("whatever") Then
msgbox("Word(s) found " & line)
Do_this_and_that()
Else
MsgBox("Word(s) not found")
Exit While
End If
End While
End Using
Else
msgbox("File not found")
End If
There seem to be so many variations of doing this, but I can't get them to work when its multiple words instead of just one. What is the easies and cleanest way of doing this?

You need to tokenize the line and use a HashSet. That is the fastest method. Put all the words in the HashSet and then check if each word is init:
static void Main()
{
var file = #"C:\application\thefile";
var hashSet = new HashSet<string>(new[] { "banana", "horse", "window", "whatever" }.Select(x => x.ToLower()));
foreach (var word in GetWords(file))
{
Console.WriteLine(word);
if (hashSet.Contains(word))
{
//DoSomething();
Console.WriteLine("\tFound!!");
//Continue or Break;
}
}
}
private static IEnumerable<string> GetWords(string file)
{
var rg = new Regex(#"[^\p{L}]");
const int bufferLen = 512;
using (var reader = File.OpenText(file))
{
var word = new StringBuilder();
while (!reader.EndOfStream)
{
var buffer = new char[bufferLen];
var readChars = reader.ReadBlock(buffer, 0, bufferLen);
for (int i = 0; i < readChars; i++)
{
if (rg.IsMatch(buffer[i].ToString()))//end of the word
{
if (word.Length > 0)
{
yield return word.ToString();
word = new StringBuilder();
}
}
else
word.Append(Char.ToLowerInvariant(buffer[i]));
}
}
if (word.Length > 0)
yield return word.ToString();
}
}
and here in VB
Imports System.Text.RegularExpressions
Imports System.IO
Imports System.Text
Module Module1
Sub Main()
Dim filename = "C:\application\thefile"
Dim words() As String = {"banana", "horse", "window", "whatever"}
Dim bagOfWords = New HashSet(Of String)(words.Select(Function(x) x.ToLower()))
For Each word As String In GetWords(filename)
Console.WriteLine(word)
If bagOfWords.Contains(word) Then
'DoSomething();
Console.WriteLine(vbTab & "Found!!")
'Exit For if you need to terminate here;
End If
Next
End Sub
Private Iterator Function GetWords(filename As String) As IEnumerable(Of String)
Dim rg = New Regex("[^\p{L}]")
Const bufferLen As Integer = 512
Using reader As New StreamReader(filename)
Dim word = New StringBuilder()
While Not reader.EndOfStream
Dim buffer = New Char(bufferLen - 1) {}
Dim readChars = reader.ReadBlock(buffer, 0, bufferLen)
For i As Integer = 0 To readChars - 1
If rg.IsMatch(buffer(i).ToString()) Then
'end of the word
If word.Length > 0 Then
Yield word.ToString()
word = New StringBuilder()
End If
Else
word.Append([Char].ToLowerInvariant(buffer(i)))
End If
Next
End While
If word.Length > 0 Then
Yield word.ToString()
End If
End Using
End Function
End Module

This might be a bit of a performance issue, but you can try using a List(Of String) :
Dim thefile As String = "C:\application\thefile"
Dim toCheck as New List(of String)
'You can fill up your list by whoever you want
toCheck.Add("banana")
toCheck.Add("horse")
'...
Dim FoundWords As New List(Of String)
If File.Exists(thefile) Then
Using reader As New StreamReader(thefile)
While Not reader.EndOfStream
Dim line As String = reader.ReadLine()
'We check our list to see if it matches
For Each item in toCheck
if line.Contains(item) then
FoundWords.Add(item)
End If
Next
End While
End Using
If FoundWords.Count > 0 Then
msgbox(FoundWords.Count.ToString() & " Word(s) found")
Do_this_and_that()
Else
MsgBox("Word(s) not found")
End If
Else
msgbox("File not found")
End If
Now this can be improved but if you don't have thousand of words to look for that should do the trick...

Related

how to read a specific csv line vb.net

ask permission,
I created a bot to input data to the web using vb.net and selenium.
Retrieve data from csv .
How to retrieve data from csv as needed, for example, there are 100 rows, only 30-50 rows are taken, for example. The loop code should not be looped at all.
Dim textFieldParser As TextFieldParser = New TextFieldParser(TextBox1.Text) With
{
.TextFieldType = FieldType.Delimited,
.Delimiters = New String() {","}
}
drv = New ChromeDriver(options)
While Not textFieldParser.EndOfData
Try
Dim strArrays As String() = textFieldParser.ReadFields()
Dim name As String = strArrays(0)
Dim alamat As String = strArrays(1)
Dim notlp As String = strArrays(2)
drv.Navigate().GoToUrl("URL")
Dim Nm = drv.FindElement(By.XPath("/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[2]/input"))
Nm.SendKeys(name)
Threading.Thread.Sleep(3000)
Catch ex As Exception
MsgBox("Line " & ex.Message & "is not valid and will be skipped.")
End Try
End While
Thank you
Here's an example of using TextFieldParser to read one specific line and a specific range of lines. Note that I am using zero-based indexes for the lines. You can adjust as required if you want to use 1-based line numbers.
Public Function GetLine(filePath As String, index As Integer) As String()
Using parser As New TextFieldParser(filePath) With {.Delimiters = {","}}
Dim linesDiscarded = 0
Do Until linesDiscarded = index
parser.ReadLine()
linesDiscarded += 1
Loop
Return parser.ReadFields()
End Using
End Function
Public Function GetLines(filePath As String, startIndex As Integer, count As Integer) As List(Of String())
Using parser As New TextFieldParser(filePath) With {.Delimiters = {","}}
Dim linesDiscarded = 0
Do Until linesDiscarded = startIndex
parser.ReadLine()
linesDiscarded += 1
Loop
Dim lines As New List(Of String())
Do Until lines.Count = count
lines.Add(parser.ReadFields())
Loop
Return lines
End Using
End Function
Simple loops to skip and to take lines.

VB.Net Merge multiple pdfs into one and export

I have to merge multiple PDFs into a single PDF.
I am using the iText.sharp library, and collect converted the code and tried to use it (from here)
The actual code is in C# and I converted that to VB.NET.
Private Function MergeFiles(ByVal sourceFiles As List(Of Byte())) As Byte()
Dim mergedPdf As Byte() = Nothing
Using ms As New MemoryStream()
Using document As New Document()
Using copy As New PdfCopy(document, ms)
document.Open()
For i As Integer = 0 To sourceFiles.Count - 1
Dim reader As New PdfReader(sourceFiles(i))
' loop over the pages in that document
Dim n As Integer = reader.NumberOfPages
Dim page As Integer = 0
While page < n
page = page + 1
copy.AddPage(copy.GetImportedPage(reader, page))
End While
Next
End Using
End Using
mergedPdf = ms.ToArray()
End Using
End Function
I am now getting the following error:
An item with the same key has already been added.
I did some debugging and have tracked the problem down to the following lines:
copy.AddPage(copy.GetImportedPage(reader,
copy.AddPage(copy.GetImportedPage(reader, page)))
Why is this error happening?
I have a console that monitors individual folders in a designated folder then needs to merge all of the pdf's in that folder into a single pdf. I pass an array of file paths as strings and the output file i would like.
This is the function i use.
Public Shared Function MergePdfFiles(ByVal pdfFiles() As String, ByVal outputPath As String) As Boolean
Dim result As Boolean = False
Dim pdfCount As Integer = 0 'total input pdf file count
Dim f As Integer = 0 'pointer to current input pdf file
Dim fileName As String
Dim reader As iTextSharp.text.pdf.PdfReader = Nothing
Dim pageCount As Integer = 0
Dim pdfDoc As iTextSharp.text.Document = Nothing 'the output pdf document
Dim writer As PdfWriter = Nothing
Dim cb As PdfContentByte = Nothing
Dim page As PdfImportedPage = Nothing
Dim rotation As Integer = 0
Try
pdfCount = pdfFiles.Length
If pdfCount > 1 Then
'Open the 1st item in the array PDFFiles
fileName = pdfFiles(f)
reader = New iTextSharp.text.pdf.PdfReader(fileName)
'Get page count
pageCount = reader.NumberOfPages
pdfDoc = New iTextSharp.text.Document(reader.GetPageSizeWithRotation(1), 18, 18, 18, 18)
writer = PdfWriter.GetInstance(pdfDoc, New FileStream(outputPath, FileMode.OpenOrCreate))
With pdfDoc
.Open()
End With
'Instantiate a PdfContentByte object
cb = writer.DirectContent
'Now loop thru the input pdfs
While f < pdfCount
'Declare a page counter variable
Dim i As Integer = 0
'Loop thru the current input pdf's pages starting at page 1
While i < pageCount
i += 1
'Get the input page size
pdfDoc.SetPageSize(reader.GetPageSizeWithRotation(i))
'Create a new page on the output document
pdfDoc.NewPage()
'If it is the 1st page, we add bookmarks to the page
'Now we get the imported page
page = writer.GetImportedPage(reader, i)
'Read the imported page's rotation
rotation = reader.GetPageRotation(i)
'Then add the imported page to the PdfContentByte object as a template based on the page's rotation
If rotation = 90 Then
cb.AddTemplate(page, 0, -1.0F, 1.0F, 0, 0, reader.GetPageSizeWithRotation(i).Height)
ElseIf rotation = 270 Then
cb.AddTemplate(page, 0, 1.0F, -1.0F, 0, reader.GetPageSizeWithRotation(i).Width + 60, -30)
Else
cb.AddTemplate(page, 1.0F, 0, 0, 1.0F, 0, 0)
End If
End While
'Increment f and read the next input pdf file
f += 1
If f < pdfCount Then
fileName = pdfFiles(f)
reader = New iTextSharp.text.pdf.PdfReader(fileName)
pageCount = reader.NumberOfPages
End If
End While
'When all done, we close the document so that the pdfwriter object can write it to the output file
pdfDoc.Close()
result = True
End If
Catch ex As Exception
Return False
End Try
Return result
End Function
the code that was marked correct does not close all the file streams therefore the files stay open within the app and you wont be able to delete unused PDFs within your project
This is a better solution:
Public Sub MergePDFFiles(ByVal outPutPDF As String)
Dim StartPath As String = FileArray(0) ' this is a List Array declared Globally
Dim document = New Document()
Dim outFile = Path.Combine(outPutPDF)' The outPutPDF varable is passed from another sub this is the output path
Dim writer = New PdfCopy(document, New FileStream(outFile, FileMode.Create))
Try
document.Open()
For Each fileName As String In FileArray
Dim reader = New PdfReader(Path.Combine(StartPath, fileName))
For i As Integer = 1 To reader.NumberOfPages
Dim page = writer.GetImportedPage(reader, i)
writer.AddPage(page)
Next i
reader.Close()
Next
writer.Close()
document.Close()
Catch ex As Exception
'catch a Exception if needed
Finally
writer.Close()
document.Close()
End Try
End Sub
I realize I'm pretty late to the party, but after reading the comments from #BrunoLowagie, I wanted to see if I could put something together myself that uses the examples from his linked sample chapter. It's probably overkill, but I put together some code that merges multiple PDFs into a single file that I posted on the Code Review SE site (the post, VB.NET - Error Handling in Generic Class for PDF Merge, contains the full class code). It only merges PDF files right now, but I'm planning on adding methods for additional functionality later.
The "master" method (towards the end of the Class block in the linked post, and also posted below for reference) handles the actual merging of the PDF files, but the multiple overloads provide a number of options for how to define the list of original files. So far, I've included the following features:
The methods return a System.IO.FileInfo object if the merge is successful.
Provide a System.IO.DirectoryInfo object or a System.String identifying a path and it will collect all PDF files in that directory (including sub-directories if specified) to merge.
Provide a List(Of System.String) or a List(Of System.IO.FileInfo) specifying the PDFs you want to merge.
Identify how the PDFs should be sorted before the merge (especially useful if you use one of the MergeAll methods to get all PDF files in a directory).
If the specified output PDF file already exists, you can specify whether or not you want to overwrite it. (I'm considering adding the "ability" to automatically adjust the output PDF file's name if it already exists).
Warning and Error properties provide a way to get feedback in the calling method, whether or not the merge is successful.
Once the code is in place, it can be used like this:
Dim PDFDir As New IO.DirectoryInfo("C:\Test Data\PDF\")
Dim ResultFile As IO.FileInfo = Nothing
Dim Merger As New PDFManipulator
ResultFile = Merger.MergeAll(PDFDir, "C:\Test Data\PDF\Merged.pdf", True, PDFManipulator.PDFMergeSortOrder.FileName, True)
Here is the "master" method. As I said, it's probably overkill (and I'm still tweaking it some), but I wanted to do my best to try to make it work as effectively as possible. Obviously it requires a Reference to the itextsharp.dll for access to the library's functions.
I've commented out the references to the Error and Warning properties of the class for this post to help reduce any confusion.
Public Function Merge(ByVal PDFFiles As List(Of System.IO.FileInfo), ByVal OutputFileName As String, ByVal OverwriteExistingPDF As Boolean, ByVal SortOrder As PDFMergeSortOrder) As System.IO.FileInfo
Dim ResultFile As System.IO.FileInfo = Nothing
Dim ContinueMerge As Boolean = True
If OverwriteExistingPDF Then
If System.IO.File.Exists(OutputFileName) Then
Try
System.IO.File.Delete(OutputFileName)
Catch ex As Exception
ContinueMerge = False
'If Errors Is Nothing Then
' Errors = New List(Of String)
'End If
'Errors.Add("Could not delete existing output file.")
Throw
End Try
End If
End If
If ContinueMerge Then
Dim OutputPDF As iTextSharp.text.Document = Nothing
Dim Copier As iTextSharp.text.pdf.PdfCopy = Nothing
Dim PDFStream As System.IO.FileStream = Nothing
Dim SortedList As New List(Of System.IO.FileInfo)
Try
Select Case SortOrder
Case PDFMergeSortOrder.Original
SortedList = PDFFiles
Case PDFMergeSortOrder.FileDate
SortedList = PDFFiles.OrderBy(Function(f As System.IO.FileInfo) f.LastWriteTime).ToList
Case PDFMergeSortOrder.FileName
SortedList = PDFFiles.OrderBy(Function(f As System.IO.FileInfo) f.Name).ToList
Case PDFMergeSortOrder.FileNameWithDirectory
SortedList = PDFFiles.OrderBy(Function(f As System.IO.FileInfo) f.FullName).ToList
End Select
If Not IO.Directory.Exists(New IO.FileInfo(OutputFileName).DirectoryName) Then
Try
IO.Directory.CreateDirectory(New IO.FileInfo(OutputFileName).DirectoryName)
Catch ex As Exception
ContinueMerge = False
'If Errors Is Nothing Then
' Errors = New List(Of String)
'End If
'Errors.Add("Could not create output directory.")
Throw
End Try
End If
If ContinueMerge Then
OutputPDF = New iTextSharp.text.Document
PDFStream = New System.IO.FileStream(OutputFileName, System.IO.FileMode.OpenOrCreate)
Copier = New iTextSharp.text.pdf.PdfCopy(OutputPDF, PDFStream)
OutputPDF.Open()
For Each PDF As System.IO.FileInfo In SortedList
If ContinueMerge Then
Dim InputReader As iTextSharp.text.pdf.PdfReader = Nothing
Try
InputReader = New iTextSharp.text.pdf.PdfReader(PDF.FullName)
For page As Integer = 1 To InputReader.NumberOfPages
Copier.AddPage(Copier.GetImportedPage(InputReader, page))
Next page
If InputReader.IsRebuilt Then
'If Warnings Is Nothing Then
' Warnings = New List(Of String)
'End If
'Warnings.Add("Damaged PDF: " & PDF.FullName & " repaired and successfully merged into output file.")
End If
Catch InvalidEx As iTextSharp.text.exceptions.InvalidPdfException
'Skip this file
'If Errors Is Nothing Then
' Errors = New List(Of String)
'End If
'Errors.Add("Invalid PDF: " & PDF.FullName & " not merged into output file.")
Catch FormatEx As iTextSharp.text.pdf.BadPdfFormatException
'Skip this file
'If Errors Is Nothing Then
' Errors = New List(Of String)
'End If
'Errors.Add("Bad PDF Format: " & PDF.FullName & " not merged into output file.")
Catch PassworddEx As iTextSharp.text.exceptions.BadPasswordException
'Skip this file
'If Errors Is Nothing Then
' Errors = New List(Of String)
'End If
'Errors.Add("Password-protected PDF: " & PDF.FullName & " not merged into output file.")
Catch OtherEx As Exception
ContinueMerge = False
Finally
If Not InputReader Is Nothing Then
InputReader.Close()
InputReader.Dispose()
End If
End Try
End If
Next PDF
End If
Catch ex As iTextSharp.text.pdf.PdfException
ResultFile = Nothing
ContinueMerge = False
'If Errors Is Nothing Then
' Errors = New List(Of String)
'End If
'Errors.Add("iTextSharp Error: " & ex.Message)
If System.IO.File.Exists(OutputFileName) Then
If Not OutputPDF Is Nothing Then
OutputPDF.Close()
OutputPDF.Dispose()
End If
If Not PDFStream Is Nothing Then
PDFStream.Close()
PDFStream.Dispose()
End If
If Not Copier Is Nothing Then
Copier.Close()
Copier.Dispose()
End If
System.IO.File.Delete(OutputFileName)
End If
Throw
Catch other As Exception
ResultFile = Nothing
ContinueMerge = False
'If Errors Is Nothing Then
' Errors = New List(Of String)
'End If
'Errors.Add("General Error: " & other.Message)
If System.IO.File.Exists(OutputFileName) Then
If Not OutputPDF Is Nothing Then
OutputPDF.Close()
OutputPDF.Dispose()
End If
If Not PDFStream Is Nothing Then
PDFStream.Close()
PDFStream.Dispose()
End If
If Not Copier Is Nothing Then
Copier.Close()
Copier.Dispose()
End If
System.IO.File.Delete(OutputFileName)
End If
Throw
Finally
If Not OutputPDF Is Nothing Then
OutputPDF.Close()
OutputPDF.Dispose()
End If
If Not PDFStream Is Nothing Then
PDFStream.Close()
PDFStream.Dispose()
End If
If Not Copier Is Nothing Then
Copier.Close()
Copier.Dispose()
End If
If System.IO.File.Exists(OutputFileName) Then
If ContinueMerge Then
ResultFile = New System.IO.FileInfo(OutputFileName)
If ResultFile.Length <= 0 Then
ResultFile = Nothing
Try
System.IO.File.Delete(OutputFileName)
Catch ex As Exception
Throw
End Try
End If
Else
ResultFile = Nothing
Try
System.IO.File.Delete(OutputFileName)
Catch ex As Exception
Throw
End Try
End If
Else
ResultFile = Nothing
End If
End Try
End If
Return ResultFile
End Function
Some may have to make a change to the code at "writer = PdfWriter.GetInstance(pdfDoc, New FileStream(outputPath, FileMode.OpenOrCreate))" as iTextSharp may not support
Change to:
Dim fs As IO.FileStream = New IO.FileStream(outputPath, IO.FileMode.Create)
writer = iTextSharp.text.pdf.PdfWriter.GetInstance(pdfDoc, fs)

Parsing in Json not in XML . VB.Net

At the moment I am using VB.Net.
I build my string, post it out and then parse the results.
Parsing Example for XML
Dim xml As New MWXMLDocument()
Dim sReason As String = "Unknown"
Try
xml.LoadXml(sresult)
If xml.SelectSimpleNode("AcceptedLead").InnerText = "true" Then
app.Outcome.RedirectURL = xml.SelectSimpleNode("result/redirecturl").InnerText
AcceptLead()
Return True
End If
sReason = xml.SelectSimpleNode("Reason").InnerText
Catch ex As Exception
sReason = "Error: " & ex.Message
End Try
DeclineLead(sReason)
Return False
End Function
How would I parse a result sent back in JSON, here is an example of the result I want to parse in using VB : Can i not just get the data from the string and parse as normal XML.
{"RedirectUrl":"www.test.com","Commission":5.0000,"Status":"accepted"}
You can use the JSON.NET Library
Example in C#:
var result = JsonConvert.DeserializeObject<RootObject>(string json);
The RootObject should be your own class.
You could use the .Net built in JavaScriptSerialiser
First add a reference to System.Web.Extensions and then
Imports System.Web.Script.Serialization
Followed by...
Dim sExampleJSON As String = "{""RedirectUrl"":""www.test.com"",""Commission"":5.0000,""Status"":""accepted""}"
Dim MySerializer As JavaScriptSerializer = New JavaScriptSerializer()
Dim MyDictionary As Dictionary(Of String, Object) = MySerializer.Deserialize(Of Dictionary(Of String, Object))(sExampleJSON)
If MyDictionary.ContainsKey("RedirectUrl") Then
Console.WriteLine(MyDictionary("RedirectUrl"))
End If
in global.asax.cs
using System.Data.Entity;
namespace RpManticSolAPI
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
}
}
}
The complete Answer
sResult = sResult.Replace("""", String.Empty)
If sResult.Contains("Status:accepted") Then
Dim parts = sResult.Replace("{", String.Empty).Replace("}", String.Empty).Split(",")
For i As Int16 = 0 To parts.Length - 1
If parts(i).StartsWith("RedirectUrl") Then
app.Outcome.RedirectURL = parts(i).Substring(12)
End If
If parts(i).StartsWith("Commission") Then
lendertier.LenderComm = CDec(parts(i).Substring(11))
End If
If parts(i).StartsWith("ApplicationRef") Then
app.Outcome.LenderReference = parts(i).Substring(15)
End If
Next
AcceptLead()
Return True
End If
If sResult.Contains("Reason:Duplicate") Then
sReason = "Duplicate"
ElseIf sResult.Contains("{Error:invalid credentials") Then
sReason = "Error: Invalid credentials"
ElseIf sResult.Contains("ValidationErrors:") Then
sReason = "Invalid call:" + sResult.Replace("ValidationErrors:", String.Empty).Replace(",Status:rejected", String.Empty)
Else
sReason = "Rejected"
End If
DeclineLead(sReason)
Return False

Get Notepad Number of Pages before Print

I'm trying to get the number of pages notepad before print,
I'm setting the notepad to wordwrap=true, FontSize=12, MarginRight=750, MarginLeft=750, MarginTop=1000, MarginBottom=1000,
Greater than 70 is the number of column for page is equal to 1 and 51 is the number of line when page is equal to 1 also.
It's working But some mistakes on the formula I have, some notepad pages gets Ok, but some are not.
I hope someone could correct the code what I have.
Or is there any proper code to get this done even if notepad settings are changed, if there is no proper way of getting the notepad pages, at-least someone could correct the code I have.
Thanks.
Private Function GetNotepadNumPage(ByVal filename as string) as Integer
Dim sr As New StreamReader(filename)
Dim line As String = sr.ReadLine
Dim CharL(9999) As Integer
Dim pCount As Integer = 0
Dim pLine As Integer = 0
Do While Not sr.EndOfStream
line = sr.ReadLine()
CharL(pLine) = line.Length
pLine += 1
If pLine = 51 Then
pCount += 1
For i As Integer = 0 To pLine
If CharL(i) > 70 Then
pCount += 1
Exit For
End If
Next
pLine = 0
End If
Loop
sr.Close()
If (pLine <> 0) Then
pCount += 1
For i As Integer = 0 To pLine
If CharL(i) > 70 Then
pCount += 1
Exit For
End If
Next
End If
pagecount = pCount
Return pagecount
End Function
Here's a simple wrapper class for printing text in .net. It's written in C# but ifairly straight forward. It includes calculations for measuring each page. You might be able to use this:
using System;
using System.Drawing;
using System.Drawing.Printing;
namespace PrintDocClass
{
public class PrintDoc
{
private PrintDocument pd1 = new PrintDocument();
private Font _pdfont = new Font("Microsoft Sans Serif", 8.25f);
private string _PrintString = "";
private string _Name = "";
private bool _Landscape = false;
public PrintDoc(string PrintString, bool Landscape = false)
{
_PrintString = PrintString;
_Landscape = Landscape;
}
public PrintDoc(string PrintString, string DocName, bool Landscape = false)
{
_PrintString = PrintString;
_Name = DocName;
_Landscape = Landscape;
}
public PrintDoc(string PrintString, string DocName, Font PrintFont, bool Landscape = false)
{
_PrintString = PrintString;
_Name = DocName;
_pdfont = PrintFont;
_Landscape = Landscape;
}
public void Print()
{
pd1.DefaultPageSettings.Landscape = _Landscape;
pd1.PrintPage += new PrintPageEventHandler(pd1_PrintPage);
if (_Name != "")
_PrintString = _Name + "\n\n" + _PrintString;
pd1.Print();
}
private void pd1_PrintPage(object sender, PrintPageEventArgs e)
{
int charactersOnPage = 0;
int linesPerPage = 0;
// Sets the value of charactersOnPage to the number of characters
// of stringToPrint that will fit within the bounds of the page.
e.Graphics.MeasureString(_PrintString, _pdfont,
e.MarginBounds.Size, StringFormat.GenericTypographic,
out charactersOnPage, out linesPerPage);
// Draws the string within the bounds of the page
e.Graphics.DrawString(_PrintString, _pdfont, Brushes.Black,
e.MarginBounds, StringFormat.GenericTypographic);
// Remove the portion of the string that has been printed.
_PrintString = _PrintString.Substring(charactersOnPage);
// Check to see if more pages are to be printed.
e.HasMorePages = (_PrintString.Length > 0);
}
}
}
You can use this ..
Private Function GetNotepadNumPage(ByVal filename As String) As Integer
Dim sr As New StreamReader(filename)
Dim sLine As String
Dim sBuff As String
Dim nPage As Integer = 0
Dim nLine As Integer = 0
Dim n As Integer
Do While Not sr.EndOfStream
sLine = sr.ReadLine()
sBuff = sBuff & sLine
If sBuff.Length > 70 Then
n = sBuff.Length \ 70
nLine += n
sBuff = Mid(sBuff, 70 * n + 1)
'MsgBox(sBuff)
End If
If nLine > 51 Then
nPage += 1
nLine = nLine - 51
End If
Loop
'probably sBuff not empty
If sBuff.Length > 0 Then
nLine += 1
If nLine = 1 Or nPage = 0 Then nPage += 1
End If
Return nPage
End Function
End Class

Need C# code converted to VB.NET for Silverlight "Export to CSV" [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 12 years ago.
Improve this question
I'm looking to get the following code converted to working VB.NET code. I need to export data from a datagrid into the CSV format that the user can save off, and the code below from David in Dakota would work great, but it's in C#. Any help would be appreciated! This is for a Silverlight 4 site we're working on.
private void exportHistoryButton_Click(object sender, RoutedEventArgs e)
{
string data = ExportDataGrid(true, historyDataGrid);
SaveFileDialog sfd = new SaveFileDialog()
{
DefaultExt = "csv",
Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*",
FilterIndex = 1
};
if (sfd.ShowDialog() == true)
{
using (Stream stream = sfd.OpenFile())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(data);
writer.Close();
}
stream.Close();
}
}
}
private string FormatCSVField(string data)
{
return String.Format(
"\"{0}\"",
data.Replace("\"", "\"\"\"")
.Replace("\n", "")
.Replace("\r", "")
);
}
public string ExportDataGrid(bool withHeaders, DataGrid grid)
{
string colPath;
System.Reflection.PropertyInfo propInfo;
System.Windows.Data.Binding binding;
System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
System.Collections.IList source = (grid.ItemsSource as System.Collections.IList);
if (source == null)
return "";
List<string> headers = new List<string>();
grid.Columns.ToList().ForEach(col =>
{
if (col is DataGridBoundColumn)
{
headers.Add(FormatCSVField(col.Header.ToString()));
}
});
strBuilder
.Append(String.Join(",", headers.ToArray()))
.Append("\r\n");
foreach (Object data in source)
{
List<string> csvRow = new List<string>();
foreach (DataGridColumn col in grid.Columns)
{
if (col is DataGridBoundColumn)
{
binding = (col as DataGridBoundColumn).Binding;
colPath = binding.Path.Path;
propInfo = data.GetType().GetProperty(colPath);
if (propInfo != null)
{
csvRow.Add(FormatCSVField(propInfo.GetValue(data, null).ToString()));
}
}
}
strBuilder.Append(String.Join(",", csvRow.ToArray())).Append("\r\n");
}
return strBuilder.ToString();
}
You may try a free online conversion tool.
Here's a mostly-direct translation. I made a few improvements but left if close enough to original that you should still recognize it. But we can do a lot better, so keep reading after this initial attempt for something better:
Private Sub exportHistoryButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim sfd As New SaveFileDialog()
sfd.DefaultExt = "csv"
sfd.Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*"
sfd.FilterIndex = 1
If sfd.ShowDialog() Then
Using writer As New StreamWriter(sfd.OpenFile())
writer.Write(ExportDataGrid(True, historyDataGrid))
End Using
End If
End Sub
Private Function FormatCSVField(ByVal data As String) As String
Return String.Format("""{0}""", _
data.Replace("""", """""").Replace(vbLf, "").Replace(vbCr, ""))
End Function
Public Function ExportDataGrid(ByVal withHeaders As Bool, ByVal grid As DataGrid) As String
Dim source As System.Collections.IList = TryCast(grid.ItemsSource, System.Collections.IList)
If source Is Nothing Then Return ""
Dim builder As New System.Text.StringBuilder()
If withHeaders Then
Dim headers As new List(Of String)()
For Each col As DataColumn In grid.Columns.Where(Function(c) TypeOf c is DataGridBoundColumn)
headers.Add(FormatCSVField(col.Header.ToString()))
Next col
builder.Append(String.Join(",", headers.ToArray())).Append(vbCrLf)
End If
For Each row in source
Dim csvRow As New List(Of String)()
For Each col As DataGridBoundColumn in grid.Columns.Where(Function(c) TypeOf col Is DataGridBoundColumn)
Dim propInfo As System.Reflection.PropertyInfo = _
row.GetType().GetProperty(col.Binding.Path.Path)
If propInfo IsNot Nothing Then
csvRow.Add(FormatCSVField(propInfo.GetValue(row, Nothing).ToString()))
End If
Next col
builder.Append(String.Join(",", csvRow.ToArray())).Append(vbCrLf)
Next row
Return builder.ToString()
End Function
The big problem with this code is that when you put your entire grid into a single string variable, you create an object that will very likely end up on the Large Object Heap. This is a "Bad Thing"™. One of the things that makes it so bad is that it often doesn't look bad in your performance testing. It's the kind of problem that won't show up until production. But trust me when I say we can do better.
If this were still going to be C# I'd refactor it to use an iterator block to yield return the string for one row at a time, and then write that out. Since it's VB, we'll refactor it to accept a TextWriter and write directly to that:
Private Sub exportHistoryButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim sfd As New SaveFileDialog()
sfd.DefaultExt = "csv"
sfd.Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*"
sfd.FilterIndex = 1
If sfd.ShowDialog() Then
Using writer As New StreamWriter(sfd.OpenFile())
ExportDataGrid(historyDataGrid, writer) ' Notice the change here
End Using
End If
End Sub
Private Function WriteCSVField(ByVal data As String, ByVal writer As TextWriter) As String
' This would likely do a _lot_ better with a state machine to iterate over
' each character rather than create 3 new strings for every field,
' but we'll let it slide for now
writer.Write(""""c)
writer.Write(data.Replace("""", """""").Replace(vbLf, "").Replace(vbCr, ""))
writer.Write(""""c)
End Function
' Notice the new function signature
Public Sub ExportDataGrid(ByVal grid As DataGrid, ByVal writer As TextWriter, Optional ByVal WithHeaders As Boolean = True)
Dim source As System.Collections.IList = TryCast(grid.ItemsSource, System.Collections.IList)
If source Is Nothing Then Return ""
Dim delimiter As String
If WithHeaders Then
delimiter = ""
For Each col As DataColumn In grid.Columns.Where(Function(c) TypeOf c is DataGridBoundColumn)
writer.Write(delimiter)
WriteCSVField(col.Header.ToString(), writer)
delimiter = ","
Next col
writer.Write(vbCrLf)
End If
For Each row In source
delimiter = ""
For Each col As DataGridBoundColumn in grid.Columns.Where(Function(c) TypeOf col Is DataGridBoundColumn)
writer.Write(delimiter)
delimiter = ","
' I'm pretty sure this could be refactored to avoid the reflection,
' But I also think there's a bug in your code here, so I'll
' leave the direct translation for now
Dim propInfo As System.Reflection.PropertyInfo = _
row.GetType().GetProperty(col.Binding.Path.Path)
If propInfo IsNot Nothing Then
WriteCSVField(propInfo.GetValue(row, Nothing).ToString(), writer)
End If
Next col
writer.Write(vbCrLf)
Next row
End Sub
Of course, the best option of all here is to write no new code at all for a problem that's already been solved by thousands of other programmers. You can just go get an existing library that turn this whole mess into two or lines calling into that API.
This isn't a question, it's a request. But try this:
http://www.developerfusion.com/tools/convert/csharp-to-vb/
Private Sub exportHistoryButton_Click(sender As Object, e As RoutedEventArgs)
Dim data As String = ExportDataGrid(True, historyDataGrid)
Dim sfd As New SaveFileDialog() With { _
.DefaultExt = "csv", _
.Filter = "CSV Files (.csv)|.csv|All files (.)|.", _
.FilterIndex = 1 _
}
If sfd.ShowDialog() = True Then
Using stream As Stream = sfd.OpenFile()
Using writer As New StreamWriter(stream)
writer.Write(data)
writer.Close()
End Using
stream.Close()
End Using
End If
End Sub
Private Function FormatCSVField(data As String) As String
Return [String].Format("""{0}""", data.Replace("""", """""""").Replace(vbLf, "").Replace(vbCr, ""))
End Function
Public Function ExportDataGrid(withHeaders As Boolean, grid As DataGrid) As String
Dim colPath As String
Dim propInfo As System.Reflection.PropertyInfo
Dim binding As System.Windows.Data.Binding
Dim strBuilder As New System.Text.StringBuilder()
Dim source As System.Collections.IList = TryCast(grid.ItemsSource, System.Collections.IList)
If source Is Nothing Then
Return ""
End If
Dim headers As New List(Of String)()
grid.Columns.ToList().ForEach(Function(col) Do
If TypeOf col Is DataGridBoundColumn Then
headers.Add(FormatCSVField(col.Header.ToString()))
End If
End Function)
strBuilder.Append([String].Join(",", headers.ToArray())).Append(vbCr & vbLf)
For Each data As [Object] In source
Dim csvRow As New List(Of String)()
For Each col As DataGridColumn In grid.Columns
If TypeOf col Is DataGridBoundColumn Then
binding = TryCast(col, DataGridBoundColumn).Binding
colPath = binding.Path.Path
propInfo = data.[GetType]().GetProperty(colPath)
If propInfo IsNot Nothing Then
csvRow.Add(FormatCSVField(propInfo.GetValue(data, Nothing).ToString()))
End If
End If
Next
strBuilder.Append([String].Join(",", csvRow.ToArray())).Append(vbCr & vbLf)
Next
Return strBuilder.ToString()
End Function