How to generate asci file to virtual pdf printer in vb.net. I tried with the virtual printer "microsoft print to pdf" it didn't work. I also found the link below but I don't understand whether it can used with the language of the vb.net program. Please the best solution.
http://www.columbia.edu/~em36/ghostpcl.html
below is a link to share the asci file so it's easy to try
Here's a link!
I use a dosprinter evaluation copy and it can produce the same output according to the output of the dot matrix printer so I think there must be other ways or solutions to achieve the same result. below share the pdf file
Here's a link!
Public Shared Function SendFileToPrinter(ByVal szPrinterName As String, ByVal szFileName As String) As Boolean
' Open the file.
'FileStream and BinaryReader are disposable objects. Hence you need to dispose of these objects Better if you declare them with a Using statement, so there's a very good chance they're disposed even when an exception is generated in the meanwhile. -- Disposing of disposable objects is not exactly optional.
Using fs As New FileStream(szFileName, FileMode.Open)
' Create a BinaryReader on the file.
Dim br As New BinaryReader(fs)
' Dim an array of bytes big enough to hold the file's contents.
Dim bytes(fs.Length - 1) As Byte
Dim bSuccess As Boolean = False
' Your unmanaged pointer.
Dim pUnmanagedBytes As New IntPtr(0)
Dim nLength As Integer
nLength = Convert.ToInt32(fs.Length)
' Read the contents of the file into the array.
bytes = br.ReadBytes(nLength)
' Allocate some unmanaged memory for those bytes.
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength)
' Copy the managed byte array into the unmanaged array.
Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength)
' Send the unmanaged bytes to the printer.
bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength)
' Free the unmanaged memory that you allocated earlier.
Marshal.FreeCoTaskMem(pUnmanagedBytes)
Return bSuccess
End Using
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim printer As String = "Microsoft Print to PDF"
For i As Integer = 1 To 1
SendFileToPrinter(printer, "C:\vDos\#LPT1.asc")
Next i
Me.Close()
End Sub
result1
result2
view asci file
result pdf from KJ
result pdf
Your using Widows so unless your in a sandbox you can use native printing
write /pt file.doc "printer name" "printer driver name" "port address"
in this case your doc is an asc so could also be sent via notepad to the print driver.
and since your using "Microsoft Print to PDF" use that twice as both "printer name" "printer driver name", finally a file is a port of call.
write /pt "C:\vDos\#LPT1.asc" "Microsoft Print to PDF" "Microsoft Print to PDF" "c:\target\file.pdf"
Using NotePad has some differences but you require setting printer defaults so I have a printer called A4Lpdf which uses the driver and a fixed output and Write can be in colour whereas Notepad is any font as long as its Black.
notepad /pt "..\desktop\document.asc" "A4LPDF"
Later Edit
On supplying a minimal sample of your ascii.PRN file it is clearer that your input is like Epson Control codes and simple conversion to PDF is usually a disaster.
So here is a snip from an adobe print to pdf, where the two most obvious fails are underline and italic but everything is wrong as its not an image of the ink head output.
This is condensed mode
T h i s i s d o u b l e - w i d t h
T h i s is elite m o d e
T h i s i s e m p h a s i z e d m o d e
T h i s i s i t a l i c t y p e
T h i s i s d o u b l e - s t r i k e m o d e
This is under line mode
T h i s s u p e r s c r i p t
T h i s i s s u b s c r i p t
Thus we see the codes are not applied to the PDF format the same as to a matrix printer.
Potential Solutions
Either find an Epson PRN to PDF application, there are a few, (but never found a perfect one, especially for graphics art output). The codes are here https://files.support.epson.com/pdf/general/escp2ref.pdf,
OR using the printer manual plus above look-ups, use RTF replacements including images, for a close visual representation, and then use Write to print the output.rtf file to PDF.
ESC # Initialize printer
ESC P Select 10.5-point, 10-cpi
ESC C Set page length in lines ($=how many = 36 ?)
ESC M Select 10.5-point, 12-cpi (not unusual to over-ride previous setting)
W1w1 Double width spacing (WIDE FONT ON) and Double height ON (thus 21 point characters)
ESC w0 W0 Turn double-height and width printing off
However basic PDF Emulation will never be like the hardware page inked image
{\rtf1\ansi\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Perfect DOS VGA 437 Win;}{\f1\fnil\fcharset0 System;}}
{\*\generator Riched20 10.0.22000}\viewkind4\uc1
\pard\b\f0\fs14\lang2057 24 May 22\par
\par
KANA \par
\par
\par
\par
PG: 1 \fs28 SI12202041\f1\fs21 \par
\f0\fs14\par
\par
\par
\par
1 25 Pcs USB CABLE 260.000,00 6.500.000,00\par
\par
\par
\par
\par
\par
\par
\par
\par
\par
\par
\par
\par
\par
\par
\par
\par
6.500.000,00\page\f1\fs21\par
}
Its all down to finding the correct font metrics, since line printers were non-proportional fonts, but the line spaces are the fly in the ointment, they need to be pitch perfect. Thus you will need to write or find a font that EXACTLY matches the source printer styles of 10.5 points by 12cpi and 21 pts x 6 cpi (nominal) then tune them. Above is using a rough DOS VGA screen font but then I needed to adjust scales as I apply it as 7 and 14 to emulate the printers 10.5 and 21 by 70%.
It is a sloppy first shot that could be cleaned up, the key points are that RTF units are doubled expected eg 14 units = 7 pts and the language is a mix between others so \par = paragraph or line feed and the font I used is not the best but was quick to find and double click to install.
You need to read the byte codes then ignore or convert into rtf so ignoring the start printer code, replace with the string I give above using your choice of installed font name for replacing the font control codes, then convert line feeds to \par etc.
This could all be scripted in a console batch file or any language, if you store a common header (or preset pre-pends) then just change the body line by line with \par and finally add } as the trailer.
Related
This has been particularly difficult and annoying to research given the fondness of "ASCII ART". That is NOT what I am trying to do here. I need to replicate a process from an old software package that basically converts an image, any image, into ASCII text before sending it to a printer. Here is an example of what it spits out...
The first two lines are commands. The next 315 lines are pure ASCII (well they call it ASCII but its obviously hex, (80 chars ber line), followed by several more commands and setup before executing the print.
I've written all the software already, with exception to converting the image to ascii. Originally, and according to the documentation, the printer should accept raw binary data of several image types. Well, after fighting with that for the past day, I now realize why the manufacturer themselves don't go down that road.
So, my question is, how best to go about converting an image to ascii (hex) characters to send to the printer? My first guess would be to iterate through each character and convert it but that also seems like the slowest approach.
Public Shared Sub ConvertImageHex(filepath As String)
Dim f_convOutBytes() As Byte = File.ReadAllBytes(filepath)
Dim totalStreamLength As Int32 = f_convOutBytes.Length
Dim labelOutStream(totalStreamLength) As Byte
f_convOutBytes.CopyTo(labelOutStream, 0)
Dim HexValue As String = String.Empty
Dim labelPath As String = IO.Path.GetTempPath & "testasci.lbl"
If File.Exists(labelPath) Then
File.Delete(labelPath)
End If
Dim fs As FileStream = New FileStream(labelPath, FileMode.OpenOrCreate, FileAccess.ReadWrite)
Dim s As StreamWriter = New StreamWriter(fs)
s.Close()
fs.Close()
fs = New FileStream(labelPath, FileMode.OpenOrCreate, FileAccess.ReadWrite)
s = New StreamWriter(fs)
Dim i As Int32 = 0
For Each c In f_convOutBytes
i += 1
If i > 38 Then
s.Write(vbCrLf)
i = 0
End If
HexValue = Convert.ToString(Convert.ToInt32(c), 16)
s.Write(HexValue)
Next
s.Close()
fs.Close()
If Not s Is Nothing Then s = Nothing
If Not fs Is Nothing Then fs = Nothing
End Sub
Quotes from the docs (Probably too much into the weeds at this point):
d = download data
type = the type of data that will follow, using standard file name extensions
ASC - Graphic in ASCII format
ASCII graphics
ASCII-Graphic format
The stucture is similar to the IMG format, but uses only ASCII characters, to enable a easy usage for
host devices or ERP systems.
Following rules are used:
• all data are hex bytes, i.e. 0-9 and a-f or A-F
• The printer waits for data until the defined picture size is received.
• Spaces and carriage returns can be added on different locations. It is required that a
carriage return is sent at the end of the picture data.
• The image data can be compressed with a simple algorithm which is black/white
optimized.
• The image data are transmitted from top to bottom, each time from left to right. A value
byte 80 stands left of 01.
• The first line describes the width and the height of a picture. Width and height are 16 bit
values each in the Big-Endian format.
• Also if the width is not devidable by 8, it is required that the missing pixel must be
transmitted.
Each line will be transmitted with following values:
• Optional repetition factor, caused by 00 00 FF xx, whereby xx describes the amount of
copies of the current line.
• Picture data - whereby different descriptions are optional possible:
a: Zerobytes are displayed through the amount of bytes.Valid input: 00 to FF.
b: Blackbytes (FF) can also be described through the amount of bytes, beginning
from 81 (81 means 1 time FF, - valid values are 81 to FF ).
c: A directly encoded number of bytes starts with 80 - followed by the amount of data, i.e.
80 03 123456. The amout of transmitted bytes can be between 01 and 7F.
d: A repeated pattern of arbitrary bytes can be initiated with a sequence 00 nn xx, which
means that xx bytes will be inserted nn times.
Example: 00 04 AA generates AAAAAAAA.
This question already has answers here:
A Generic error occured in GDI+ in Image.Save() method
(2 answers)
Closed 6 years ago.
I have an application which creates a Bitmap object consisting of all the 16 million colors. The final bitmap would be measuring 4096 × 4096 pixels.
When I try to call the Bitmap's Save() method, it causes an error.
This is the error message that comes up:
A generic error occurred in GDI+.
Please try to help me on this thing.
Thanks in advance!
Note: Look at the last few commented lines of the source code below. I have explained the doubt there.
SOURCE CODE:
Public Sub CreateAllColorImage()
Dim BMP As New Bitmap(4096, 4096) 'This BMP variable is where the image will be created.'
Dim CurrX = 0
Dim CurrY = 0
Dim ExitFors As Boolean = False
For R = 0 To 255
For G = 0 To 255
For B = 0 To 255
BMP.SetPixel(CurrX, CurrY, Color.FromArgb(R, G, B))
CurrY += 1 'Increment the Y axis to move to next pixel.'
If CurrY > 4095 Then CurrX += 1 : CurrY = 0 'Move to next row, or increment X axis, if the last pixel on the Y axis is reached'
If CurrX > 4095 Then ExitFors = True 'Set the variable to exit the FOR loops if the very last pixel on the whole image is reached.'
If ExitFors Then Exit For 'Exit the FOR loop if the variable is true.'
Next
If ExitFors Then Exit For 'Exit the FOR loop if the variable is true.'
Next
If ExitFors Then Exit For 'Exit the FOR loop if the variable is true.'
Next
'So therefore, the final image is the BMP variable.'
'Here, I try to save the Bitmap as a file by calling this:'
BMP.Save("C:\TEST.BMP")
'This is when the error occurs. I think so because of the image is too large. If so, is there any way to do anything?'
'And by the way, I already have the rights to access the C:\ drive because I am working from an Administrator account...'
BMP.Dispose()
BMP = Nothing
End Sub
As a normal user one usually does not have access to the root C:\ drive. Even if you are an administrator your application will run under the normal privileges unless otherwise specified.
Unfortunately GDI+ hides most exceptions so it's hard to know the exact cause of what's happening, but my guess is that your problem is due to that your application isn't allowed to save directly in the C:\ drive.
Try saving the image in a path you are guaranteed to have access to, like C:\Users\YourUserName\Desktop.
It may likely be a permission problem. To test it, find your compiled .exe and run it as an administrator. If it works, you know it's a permission problem.
If you are trying to save it to your C: drive because you don't know the user name, you can instead use SpecialDirectory.
e.g.
My.Computer.FileSystem.SpecialDirectories.MyDocuments
will let you save it in the user's documents folder. Generally, saving to C: drive isn't the best thing to do.
I would also advise using the other constructor in which you can specify the image format.
e.g.
bitmapToSave.Save(saveLocation, Imaging.ImageFormat.Bmp)
I'm looking for a tool, but I can't find it. So I thought, maybe I can make one. Seems like a good idea, a program that fits my needs at last! Just one problem.. I don't know how!
Intro
At my work we create production drawings in .dwg format. Once this is done they are exported as .pdf sent to the client for approval. If approved they are issued for production, so they need to be plotted.
So my current workflow is:
Set my default printer preferences (number of copies, paper size, ..)
Go to the folder that has the .pdf files
Select 15 files
Right click print.
The problem here is
The files are printed in the order the printer receives them and not the order in the folder. So I would need to sort them out ( this x number times the number of copies sometimes this goes up to 6 times. )
I can only do 15 at a time (large projects are +100 documents)
I have to reset my preferences each time the sizes change.
Our file numbering system has some "intelligence" into it. Its build like this:
A1-12345-001 rev1
A1 = page size
12345 = document number, the same within a project. Other project means other number. (mostly irrelevant as I only print a project at a time)
001 = sequence number, next drawing will be 003,004,005,007,... you get the drift.
rev1 = revision number. Normally only the highest revision should be located in the folder, but it could be used to check for documents with a lower revision.
Now, I would like to automate my happy printing task, as this makes my week very bad if a large projects needs to go into production or, there are revisions mid-production and we need to re-issue them for production.
So far the situation sketch
Program sketch
So I've started to make a sketch of what the program should do.
User should be able to add .pdf files into a list. file browser object for starters, can be drag and drop later (the drawings are in one folder so there is no real need for drag and drop).
The list should contain 4 columns. paper size, document number, sequence, revision. Could be a data-grid view.
The list should be sorted by the drawing sequence. This how I would like to pass the drawing so, no sorting is required anymore! You can look at the sequence as page numbers.
Select the desired printer to do the job. (usually the same but other departments also have a printer so that would be a nice option.)
Set the number of copies. When printed, it shouldn't be 5x -001 then 5x -002 .. it should print them still in order of the sequence number and the re-loop the process x times.
Print the documents.
Adding PDF files
I started out with creating a dialog.. easy enough I guess.(please keep in mind that I'm a very low level programmer and nothing seems easy to me..) I added an open file dialog to my windows-form set multiple select true. Also made a filter to have only .pdf files
added a button with this code:
Private Sub ADD_FILES_Click(sender As Object, e As EventArgs) Handles ADD_FILES.Click
' Show the open file dialog. If user clicks OK, add pdf_document to list(of T)
If FileDialog.ShowDialog() = DialogResult.OK Then
Dim file As String
For Each file In FileDialog.FileNames
Debug.Print(file)
Next
End If
End Sub
So this should give me all the info I need from the file. I will edit this later, I know how to access it now!
The document object
I guess it would be wise to use some o.o.p. for this. As each file is a document and have the same required properties to make this work.
So I made a Public class for the document called PDF_Document
Public Class PDF_Document
Public FullFilePath As String
Public Property Size As String
Public Property DocNumber As String
Public Property Sequence As String
Public Property Revision As String
Public Sub New(ByVal oFilePath As String)
' Set the FullFilePath
FullFilePath = oFilePath
' Get the filename only without path.
Dim oFileName As String
oFileName = Path.GetFileName(oFilePath)
' Get the document size from the file name
Size = oFileName.Substring(0, 2)
' Get the document number from the file name
DocNumber = oFileName.Substring(3, 5)
' Get the sequence from the file name
Sequence = oFileName.Substring(9, 3)
' Chop of the .pdf from the name to get access the revision
Revision = oFileName.Substring(oFileName.Length - 5, 1)
End Sub
End Class
Well this should result into the info I need from the document..
creating a list(of t)
Wow, it seems to be getting somewhere.. Now to hold the list I'll have this collection I think don't know whats best for this? Public oPrintList As New List(Of PDF_Document)
So I think I should populate my list like this?
Public oPrintList As New List(Of PDF_Document)
Private Sub ADD_FILES_Click(sender As Object, e As EventArgs) Handles ADD_FILES.Click
' Show the open file dialog. If user clicks OK, add pdf_document to list(of T)
If FileDialog.ShowDialog() = DialogResult.OK Then
Dim oFile As String
For Each oFile In FileDialog.FileNames
Dim oPDF As New PDF_Document(oFile)
oPrintList.Add(oPDF)
Next
End If
End Sub
Making things visual for the user
Hmm okay, were getting somewhere, I got a list of all the files I need! But I want to see them in a viewer. I'm gonna use a data-grid view maybe? It should show my properties and it looks good I think.
So I made a binding that binds my List(of T) and added this binding as data-source for the data-grid view. I also change the ADD_FILES_Click a little, the PDF_Document is now added into the binding and not in the List(of T).
Public Class Form1
Public oPrintList As New List(Of PDF_Document)
Public oBinding As BindingSource
Private Sub ADD_FILES_Click(sender As Object, e As EventArgs) Handles ADD_FILES.Click
' Show the open file dialog. If user clicks OK, add pdf_document to list(of T)
If FileDialog.ShowDialog() = DialogResult.OK Then
Dim oFile As String
For Each oFile In FileDialog.FileNames
Dim oPDF As New PDF_Document(oFile)
oBinding.Add(oPDF)
Next
End If
End Sub
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
oBinding = New BindingSource(oPrintList, Nothing)
DataGridView1.DataSource = oBinding
End Sub
End Class
Printing the list
Well I managed to do quite some things now. But.. the main essence still isn't reached! I now got a form with a bunch of buttons that don't work yet, a list of select documents in queue for printing and .. thats it :)
Now I'm trying to create a method that prints a .pdf file.. easier sad than done. I need some help with this.. I search the net, but I can find samples that don't work, or I don't understand. All users PC's are equiped with acrobat reader.
Also feel free to comment me on the other parts of the program. ( yes I know there is no sorting function yet etc. ) but getting a page from the printer is more important now.
Sorry for the long post!
If your users have Adobe Acrobat Reader installed, the following code should do the trick. I recommend Acrobat Reader 11 or lower version. With Acrobat DC the window from Acrobat does not close anymore, that is a "design" decision by Adobe.
Dim pr As New Process()
pr.StartInfo.FileName = "c:\myfile.pdf"
pr.StartInfo.UseShellExecute = True
pr.StartInfo.Verb = "print"
pr.Start()
pr.WaitForExit()
I work with DWG and PDF files for 20+ years. If you are interested in a solution that fully automates all steps you explained in your "wishlist" software and does a ton more feel free to contact me at pdfmagick at gmail dot com
Another way to print PDF files with the Print Drivers dialog is as follows:
Dim starter As ProcessStartInfo
starter = New ProcessStartInfo(<pathToAdobeAcrobatExecutable>, String.Format(" /s /N /P ""{0}""", Filename))
Dim Process As New Process()
Process.StartInfo = starter
Process.Start()
Process.WaitForExit()
Process = Nothing
starter = Nothing
More command line switches are explained here
Adobe Reader Command Line Reference
Regards
I've been trying for 2 weeks to uncompress this user-defined TXXX string from an MP3 ID2,3 file.
000000B0789C6330377433D63534D575F3F737B570343767B02929CA2C4B2D4BCD2B29B6B301D376367989B9A976C519F9E50ACE1989452536FA60019B924C20696800017A10CA461F2C6AA30FD58A61427E5E72AA42228A114666E6F88CD047721100D5923799
Thanks to Dr. Adler for the correct answer when I converted the values to a string.
I have tried both MS DeflateStream and GZipstream with no success.
Every example I see uses a stream file. I am not using a file, I have the above zLib code in both an array or string variable.
GZipstream gives me 'no magic number' and Deflatestream gives me 'Block length does not match with its complement'.
I read this post:
http://george.chiramattel.com/blog/2007/09/deflatestream-block-length-does-not-match.html
tried removing bytes from the head, no luck. (I read trazillions of articles for sending a string to Deflatestream but again 'no luck'!
I have the above string, so how do I send it to Deflatestream? I'd post the two hundred different code examples I tried but that would be silly.
The funny thing is, I built my webAudio cue marker editor in less than two weeks and this is the last thing I have it do (my program must get the marker positions from a program that has worst audio editor known to man (they embedded them in the MP3 for some (bad) reason). Hence, I wrote my own to change audio cue marker so I could save hours of frustration at work. However, I'm not getting much sleep lately.
Help me get some sleep, please.
You can use a MemoryStream instead of a FileStream as they are both Streams:
Imports System.IO
Imports System.IO.Compression
Imports System.Text
Module Module1
Function HexStringToBytes(s As String) As Byte()
If (s.Length And 1) = 1 Then
Throw New ArgumentException("String is an odd number of characters in length - it must be even.")
End If
Dim bb As New List(Of Byte)
For i = 0 To s.Length - 1 Step 2
bb.Add(Convert.ToByte(s.Substring(i, 2), 16))
Next
Return bb.ToArray()
End Function
Sub Main()
Dim s = "000000B0789C6330377433D63534D575F3F737B570343767B02929CA2C4B2D4BCD2B29B6B301D376367989B9A976C519F9E50ACE1989452536FA60019B924C20696800017A10CA461F2C6AA30FD58A61427E5E72AA42228A114666E6F88CD047721100D5923799"
Dim result As String = ""
' trim off the leading zero bytes and skip the three bytes 0xB0 0x78 0x9C
Dim buffer = HexStringToBytes(s).SkipWhile(Function(b) b = 0).Skip(3).ToArray()
Using ms As New MemoryStream(buffer)
Using decompressedMemoryStream As New MemoryStream
Using decompressionStream As New DeflateStream(ms, CompressionMode.Decompress)
decompressionStream.CopyTo(decompressedMemoryStream)
result = Encoding.Default.GetString((decompressedMemoryStream.ToArray()))
End Using
End Using
End Using
Console.WriteLine(result)
Console.ReadLine()
End Sub
End Module
Outputs:
71F3-15-FOO58A77 <trivevents><event><name>show Chart</name><time>10000000.000000</time></event><event><name>show once a</name><time>26700000.000000</time></event></trivevents>
(There is a leading zero byte.)
P.S. It looks a bit strange that there is 71F3-15-FOO58A77 with letter Os instead of zeros.
P.P.S. If you could get the compressed data into a Base64 string instead of a hex string, you could pack more data into the same space.
I've been working on a label system in VB web app that prints to the Toshiba TEC Barcode printers for quite a while lately and it never seems to line up properly. I've tried changing the settings, and adjusting paper size, only re-calibrating the printer seems to help for a bit and then the alignment goes off again.
What I've been thinking of trying to do to overcome this issue is place a Button on the page that would allow the user to re-set/re-calibrate the printer. Figure this is better than them pulling on the label to line it back up again.
Here is the code used to print the label:
Public Sub SetPrintSettings(ByVal pd As PrintDocument, ByVal printer As String, ByVal printerselected As Integer)
Dim pSize As PaperSize
'set the printer
pd.PrinterSettings.PrinterName = printer
pd.DefaultPageSettings.Landscape = False
pSize = New PaperSize("USER", 400, 202)
pd.DefaultPageSettings.PaperSize = pSize
pd.DefaultPageSettings.Margins = New Margins(0, 0, 0, 0)
End Sub
I've gone through the PrinterSettings and DefaultPageSettings and there is nothing in there that will allow me to reset the printer.
Anyone have any ideas?
This is a comment really but I have put it as an answer so it formats better:
My guesses on what is causing this problem.
Too small a gap between labels. These printers can be very fussy about detecting the gap
Broken gap sensor on the printer
Incorrect commands being sent to the printer e.g. specifying a label size bigger than it actually is.