Announcement

Collapse
No announcement yet.

Create PDF-files ??

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Create PDF-files ??

    I want to create several pdf files from a PB program under Windows 10. That's fine with XPRINT. But, how can I control the file name and the folder name FROM the program?
    As far as I can see, I can't control it via XPRINT.
    Someone who knows how to do it?
    /Fim W
    Fim Wästberg

  • #2
    Not sure how much you want to get into the actual creation of PDFs, but Rick Kelly posted some code here:

    https://forum.powerbasic.com/forum/u...6422-pdf-class

    Ian.

    Comment


    • #3
      That's nothing to do with XPRINT.
      XPRINT just sends files to the printer driver and expects it to be printed, not saved to a file.

      If you're using a PDF printer driver then the file destination would be some setup within that printer driver.


      I use the free version of CutePDF but it doesn't allow programmatic choice of where the output goes. I think that's allowed in the paid for version.
      Any application that can print can be directed to the CutePDF printer and it produces the output as a PDF file.

      The free version of CutePDF does allow the name of the created files to be set using the jobname parameter of XPRINT ATTACH.

      Comment


      • #4
        Originally posted by Fim Wästberg View Post
        Someone who knows how to do it?
        See here.

        „Let the machine do the dirty work.“
        The Elements of Programming Style, Brian W. Kernighan, P. J. Plauger 1978

        Comment


        • #5
          Here's one way to use
          XPrint Attach "Microsoft Print To PDF", JobName$

          (small mod of code posted in Fim's earlier thread which uses a timer to detect when the PDF Printer Dialog is shown and insert the required Path and filename) - still pretty ugly though
          Code:
          ' Windows 10 - uses MS Print To PDF
          #Compile Exe
          #Dim All
          #Include "win32api.inc"
          
          Declare Function PostThreadMessage Lib "USER32.DLL" Alias "PostThreadMessageA" (ByVal idThread As Dword, ByVal uMsg As Dword, ByVal wParam As Dword, ByVal lParam As Long) As Long
          
          Global gsTemp As wString
          '------------------/
          
          Sub SendText(hWnd As Dword, sText As WString)
           Local tinp     As INPUTAPI
           Local i        As Long
           Local wszText  As WStringZ * %Max_Path
          
             SetForegroundWindow hWnd
             Sleep 20
              wszText = sText
              tinp.dtype   = %INPUT_KEYBOARD
              tinp.iki.wVk = 0
          
              For i = 1 To Len(wszText)
                tinp.iki.dwFlags = %KEYEVENTF_UNICODE
                tinp.iki.wScan   = Asc(Mid$(wszText, i, 1))
                SendInput 1, ByVal VarPtr(tinp), SizeOf(tinp)
          
                tinp.iki.dwFlags = %KEYEVENTF_UNICODE Or %KEYEVENTF_KEYUP
                SendInput 1, ByVal VarPtr(tinp), SizeOf(tinp)
              Next i
          End Sub
          '------------------/SendText
          
          Thread Function TimerThread(ByVal dwVar As Dword) As Long
           Static TimerID As Dword
           Local Msg      As TAGMSG
              ' Start the timer
              TimerID = SetTimer(%NULL, %NULL, 500, CodePtr(TimerProc))  ' Post %WM_TIMER msg to TimerProc every 500 msec
                                                                          ' Loop passes msg on to TimerProc until..
              While GetMessage(Msg, %NULL, %NULL, %NULL) <> 0             ' %WM_QUIT causes  GetMessage to return '0'
                DispatchMessage Msg                                       ' DispatchMessage passes %WM_TIMER on to TimerProc.
              Wend
          
            KillTimer %NULL, TimerID                                      ' Kill the timer
            WinBeep 300,500
          End Function
          '------------------/TimerThread
          
          ' Timer Proc looks for MS Print To PDF Dialog..
          Sub TimerProc(ByVal hWnd As Dword, ByVal uMsg As Long, ByVal TimerID As Long, ByVal dwTime As Dword)
            Static TimerCount As Long
            Local hMSPDF As Dword
            Select Case uMsg
              Case %WM_Timer                                              ' Timer has 'fired'
                Incr TimerCount
           '      WinBeep 500,200
                If hMSPDF = 0 Then
                  hMSPDF = FindWindow("#32770", "Save Print Output As")
                  If hMSPDF Then
                    Sleep 100
                    SendText hMSPDF, gsTemp
           '          KeyBd_Event %VK_MENU, 0, 0, 0                         ' Alt+S - Save Btn
           '          KeyBd_Event %VK_S, 0, 0, 0                            ' Automation :)
           '          KeyBd_Event %VK_S, 0, %KEYEVENTF_KEYUP, 0
           '          KeyBd_Event %VK_MENU, 0, %KEYEVENTF_KEYUP, 0
                    PostThreadMessage GetCurrentThreadID, %WM_Quit, 0, 0
                  End If
                End If
                If TimerCount = 10 Then                                    ' Bail out after n intervals
                  PostThreadMessage (GetCurrentThreadID, %WM_Quit, 0, 0)    ' Signal Quit to Msg Loop
                End If
            End Select
          End Sub
          '------------------/TimerProc
          
          Function PBMain
           Local hThread, dwVar As Dword
            gsTemp = Exe.Path$ + "JobName2"
            Thread Create TimerThread(dwVar) To hThread             ' Create monitor thread just before XPRINT Statements
            Thread Close hThread To hThread                         ' Release thread handle - not used here
          
            XPrint Attach "Microsoft Print To PDF", gsTemp          ' JobName$ not received by MS Prnt 2 PDF Dialog
           '  XPRINT ATTACH "CutePDF Writer" ', "JobName2"          ' Ok with PDFCreator and CutePDF Writer
            XPrint "Hi there gang!"
            XPrint Close
          
              Do: Sleep 50: Loop Until ThreadCount = 1
           '  ? "Done"
          End Function
          '------------------/PBMain
          Last edited by Dave Biggs; 24 Apr 2019, 09:34 PM. Reason: Noted mod of code posted in earlier thread
          Rgds, Dave

          Comment


          • #6
            I'm using a different approach to create PDF files and found it to be easier than dealing with the PDF creation itself. I create HTML files. This for me has the advantage that I can create a HTML template "sprinkled" with variables in it that I then jut replace with real content right before creation.

            Next step is to use the wkhtmltopdf command line utility to create a PDF from the HTML.

            Works great for me in an unattended endless-loop batch job environment:

            10 Create HTML
            20 Convert to PDF
            30 Send out email with PDF attached
            40 GOTO 10

            Comment


            • #7
              Knuth, I get nearly identical results to Chrome with wkhtmltopdf -- Nice find!! The results are still slightly different than FireFox (which I use for my invoices), but so close I may not care.

              For anyone who cares, Chrome Headless Printing works with this command:
              "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --headless --disable-gpu --print-to-pdf="f:\\myfiles\\filename.html.pdf" "file:F:\MyFiles\filename.html"

              Comment


              • #8
                Knuth,
                Thanks for sharing that link. Lots of potential uses for it.

                Raymond,
                Do you have a link that describes your approach? I've never heard that Chrome could do that. There's no extension required - Chrome can do that on its own?

                Comment


                • #9
                  Also, you may consider the community edition of Virtual Print Engine (VPE) I use the pro edition all the time a work, and can highly recommend it.
                  Real programmers use a magnetized needle and a steady hand

                  Comment


                  • #10
                    If you have MS Word, use COM to create the document in Word and save as PDF.

                    Cheers,
                    Dale

                    Comment


                    • #11
                      Gary, You can start here which is where I first learned of it. I also have a solution to print to PDFs from Firefox using AutoIT, but its sometimes 'delicate'. The pauses should be longer for safety, but I'm a bit on the impatient side. I'll paste that below to complete the trifecta. So far I really like Knuth's solution for everything except my invoices. The problem with my invoices is most likely in my own CSS, but I haven't the time to dig that deep right now.

                      https://developers.google.com/web/up...eadless-chrome

                      EDIT: If your pursue this, you'll likely want to read a few articles about headers/footers on Google
                      https://www.google.com/search?client...+header+footer

                      topdf.au3
                      The sleep delays and lack of concurrency make this a bad idea for bulk conversions. YMMV
                      #include <FileConstants.au3>
                      #include <WinAPIFiles.au3>
                      #include <MsgBoxConstants.au3>

                      ; Assumes the input html and output pdf are in the current directory.
                      local $fname
                      local $pname
                      local $fpid
                      $fname = "C:\Program Files\Mozilla Firefox\firefox.exe " & $CmdLine[1]
                      [email protected] & "" & $CmdLine[1] & ".pdf" & "{enter}"
                      $fpid = run($fname)
                      WinWait("III Software: Invoice")
                      WinActivate("III Software: Invoice")
                      send("^p")
                      Sleep(500)
                      send("{home}M")
                      sleep(50)
                      send("{TAB}{TAB}{enter}")
                      sleep(50)
                      send("{enter}")
                      sleep(950)
                      [email protected] & "" & $CmdLine[1] & ".pdf"
                      send($pname)
                      sleep(50)
                      send("{enter}")
                      sleep(2500)
                      send("^w")

                      Comment


                      • #12
                        Originally posted by Raymond Leech View Post
                        Knuth, I get nearly identical results to Chrome with wkhtmltopdf -- Nice find!!
                        ... which isn't too surprising, considering that both (initially*)) are based on the Webkit rendering engine, hence the "wk" in wkhtmltopdf.

                        *) Google forked Webkit in 2013 as Blink and continued from there with it as the rendering engine of Chrome/Chromium.

                        Comment


                        • #13
                          Here is an example that uses a Hook to supply a Path and Filename option for for XPRINT ATTACH when used with Microsoft's Print to PDF. (similar to post #5 which uses a timer proc).
                          It detects when the 'Save Print Output As' dialog is present and adds a Path and Filename to the input edit box.

                          It's a pity that MS supply such a sophisticated GUI for their PDF Printer but no command line options for automation

                          '
                          Code:
                          #Compile Exe
                          #Dim All
                          #Include "WIN32API.INC"
                          
                          %IDM_File      = 201
                          %IDM_Print     = 202
                          %IDM_Exit      = 203
                          %IDC_TestBtn   = 102
                          %IDC_Label1    = 101
                          %IDC_TextBox1  = 100
                          
                          $JobName = "MSPDF PrintJob.pdf"
                          Global gsJobname As wString
                          Global gsPathName As wString
                          Global ghHook As Dword
                          '------------------/
                          
                          Sub SendText(hWnd As Dword, sText As WString)
                           Local tinp   As INPUTAPI
                           Local i      As Long
                           Local wszText As WStringZ * %Max_Path
                            SetForegroundWindow hWnd
                             Sleep 20
                              wszText = sText
                              tinp.dtype   = %INPUT_KEYBOARD
                              tinp.iki.wVk = 0
                              For i = 1 To Len(wszText)
                                tinp.iki.dwFlags = %KEYEVENTF_UNICODE
                                tinp.iki.wScan   = Asc(Mid$(wszText, i, 1))
                                SendInput 1, ByVal VarPtr(tinp), SizeOf(tinp)
                          
                                tinp.iki.dwFlags = %KEYEVENTF_UNICODE Or %KEYEVENTF_KEYUP
                                SendInput 1, ByVal VarPtr(tinp), SizeOf(tinp)
                              Next i
                          End Sub
                          '------------------/SendText
                          
                          Function HookProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
                           Local szClass As Stringz * 64
                           Local szCaption  As Stringz * 64
                           Local hMSPDF, hChild As Dword
                            Function = CallNextHookEx(ByVal ghHook, ByVal nCode, ByVal wParam, ByVal lParam)
                            If nCode < 0 Then Exit Function
                            If nCode = %HCBT_ACTIVATE Then                ' MS PRINT TO PDF Dialog being activated?
                              GetClassName wParam, szClass, %Max_Path
                               If Trim$(szClass) = "#32770" Then
                                 GetWindowText wParam, szCaption, Sizeof(szCaption)
                                   If Trim$(szCaption) = "Save Print Output As" Then
                                     hMSPDF = wParam
                                     hChild = FindWindowEx(hMSPDF, 0, "DUIViewWndClassName" , "")
                                     hChild = FindWindowEx(hChild, 0, "DirectUIHWND", "")
                                     hChild = FindWindowEx(hChild, 0, "FloatNotifySink", "")
                                     hChild = FindWindowEx(hChild, 0, "ComboBox", "")
                                     hChild = FindWindowEx(hChild, 0, "Edit", "")
                                     SendText hChild, Trim$(gsPathName) + Trim$(gsJobName)
                                     UnhookWindowsHookEx ghHook
                           '           KeyBd_Event %VK_MENU, 0, 0, 0                         ' Alt+S - Save Btn
                           '           KeyBd_Event %VK_S, 0, 0, 0                            ' Automation :)
                           '           KeyBd_Event %VK_S, 0, %KEYEVENTF_KEYUP, 0
                           '           KeyBd_Event %VK_MENU, 0, %KEYEVENTF_KEYUP, 0
                                     Function = 0 : Exit Function
                                   End If
                               End If
                            End If
                          End Function
                          '------------------/HookProc
                          
                          CallBack Function DlgProc()
                            Select Case As Long CbMsg
                              Case %WM_InitDialog
                          
                              Case %WM_Command
                                Select Case As Long CbCtl
                                  Case %IDC_TestBtn, %IDM_Print
                                    If CbCtlMsg = %BN_Clicked Or CbCtlMsg = 1 Then
                                      gsPathName = Exe.Path$
                                      gsJobname = $JobName
                                      ghHook = SetWindowsHookEx(%WH_CBT, CodePtr(HookProc), GetModuleHandle(""), GetCurrentThreadId)
                          
                                      XPRINT ATTACH "Microsoft Print To PDF", $JobName    ' JobName$ not received by 'MS Prnt 2 PDF' Dialog
                                      XPrint "Sample Text etc."                           ' Initial folder = last used (Reg. Key ??)
                                      XPrint Close                                        ' Close initiates printing
                                    End If
                          
                                  Case %IdCancel, %IDM_Exit
                                    If CbCtlMsg = %BN_Clicked Or CbCtlMsg = 1 Then
                                      Dialog End CbHndl
                                    End If
                                End Select
                          
                              Case %WM_SysCommand
                                If (CbWParam And &HFFF0) = %SC_Close Then
                                  Dialog End CbHndl
                                End If
                          
                              Case %WM_Close
                          
                              Case %WM_Destroy
                                UnhookWindowsHookEx ghHook
                            End Select
                          End Function
                          '------------------/DlgProc
                          
                          Function PBMain()
                           Local hDlg, hMenu, hPopup  As Dword
                          
                            Dialog New 0, "Print Test", , , 200, 120, %WS_Caption Or %WS_SysMenu, To hDlg
                            Control Add Label,   hDlg, %IDC_Label1,   "Test Dialog", 50, 25, 120, 20
                            Control Add Button,  hDlg, %IDC_TestBtn,  "Test",        75, 60,  50, 15
                            Control Add TextBox, hDlg, %IDC_TextBox1, "TextBox1",    45, 90, 100, 13
                              hMenu = CreateMenu : hPopUp = CreatePopUpMenu
                              AppendMenu hMenu,%MF_PopUp, hPopup, "&File"
                              AppendMenu hPopUp,%MF_String, %IDM_Print, "&Print"
                              AppendMenu hPopUp,%MF_String, %IDM_Exit, "Exit"
                              SetMenu hDlg, hMenu
                            Dialog Show Modal hDlg, Call DlgProc
                          
                          End Function
                          '------------------/PbMain
                          '
                          Rgds, Dave

                          Comment


                          • #14
                            Here is the "final" solution:
                            https://www.idealsoftware.com/en/pdf...rt-engine.html
                            /Fim W.
                            Fim Wästberg

                            Comment


                            • #15
                              Originally posted by Fim Wästberg View Post
                              Here is the "final" solution:
                              https://www.idealsoftware.com/en/pdf...rt-engine.html
                              /Fim W.
                              As per Post #9 from April last year.

                              Yep, I've written a couple of applications recently that use it. The free community edition has done everything I wanted it to. (One application can generate about 1500 x 6 page statements per minute with several hundred transaction per statement being drawn from a database. )

                              Comment

                              Working...
                              X