{"id":21070806,"url":"https://github.com/fafalone/gpdfmerge","last_synced_at":"2025-05-16T05:31:11.843Z","repository":{"id":246362244,"uuid":"820702926","full_name":"fafalone/gPdfMerge","owner":"fafalone","description":"GUI-based PDF Merger ","archived":false,"fork":false,"pushed_at":"2024-07-07T08:35:39.000Z","size":24508,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-03T20:43:10.469Z","etag":null,"topics":["pdf","pdf-generation","pdf-merge","pdf-merger","pdfium","twinbasic","vb6","windows"],"latest_commit_sha":null,"homepage":"","language":"Visual Basic 6.0","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fafalone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-27T02:35:41.000Z","updated_at":"2024-07-07T08:33:20.000Z","dependencies_parsed_at":"2024-06-27T15:11:47.827Z","dependency_job_id":"65e8c547-ec2c-4ca9-a71d-98ad5b88e094","html_url":"https://github.com/fafalone/gPdfMerge","commit_stats":null,"previous_names":["fafalone/gpdfmerge"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fafalone%2FgPdfMerge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fafalone%2FgPdfMerge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fafalone%2FgPdfMerge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fafalone%2FgPdfMerge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fafalone","download_url":"https://codeload.github.com/fafalone/gPdfMerge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254473940,"owners_count":22077197,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pdf","pdf-generation","pdf-merge","pdf-merger","pdfium","twinbasic","vb6","windows"],"created_at":"2024-11-19T18:48:27.295Z","updated_at":"2025-05-16T05:31:06.833Z","avatar_url":"https://github.com/fafalone.png","language":"Visual Basic 6.0","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gPdfMerge\nGUI-based PDF Merger \n\n**Latest version:** v1.2.14, 07 July 2024\n\n![image](https://github.com/fafalone/gPdfMerge/assets/7834493/0ff980bd-99f2-4f36-b698-1320119c4994)\n\ngPdfMerge is a simple utility written in twinBASIC mainly for me to try out using pdfium.dll, Google's open source PDF utility. It will merge the selected PDFs together, either into a new file, or into the first file on the list. You can optionally specify which pages in each document should be merged, and if you're appending the first in list, where to insert them at. That's all there is to it right now; just a brief experiment before I make a 64bit version of a more complex PDF control.\n\n\n**Updates:**\n\n\u003e [!IMPORTANT]\n\u003e Starting with version 1.2, newer builds of pdfium.dll are used. These are obtained from https://github.com/bblanchon/pdfium-binaries/releases. Version 1.2 was tested with 128.0.6569.0 (01 Jul 2024), but newer versions should continue to work fine. Click 'Show all .. assets' to find the Windows versions; the file names you need are `pdfium-win-x86.tgz` and ` pdfium-win-x64.tgz`.  **gPdfMerge v1.2+ will not work with the 2018-era original DLLs used with version 1.0**.\n\n(Version 1.2 - 07 Jul 2024)\\\n-Adds a 'Search for pages' function which opens a new dialog you can use to search for a range of pages to merge:\n\n![image](https://github.com/fafalone/gPdfMerge/assets/7834493/6370de38-ea8c-4f40-91cc-c895c1456e7d)\n\n(Version 1.1)\\\n-Range entry textbox now only enabled if an item is selected.\\\n-Specifying a single pdf with page range to trim it now supported.\n\n**Build notes:**\\\nThe project is configured as follows:\\\n-The project's root folder should contain the .twinproj file, and folders `win32` and `win64` with the respective bitness version of pdfium.dll\\\n-The compiled project must have pdfium.dll in the same folder with the .exe (the build output is set to \\win32 and \\win64).\n\n\nOne thing of interest, all the VB6 samples didn't have save functionality. I wasn't positive on how to implement it at first; it uses a very VB/tB unfriendly method:\n\n```c\ntypedef struct FPDF_FILEWRITE_ {\n\n  int version;\n\n  int (*WriteBlock)(struct FPDF_FILEWRITE_* pThis,\n                    const void* pData,\n                    unsigned long size);\n} FPDF_FILEWRITE;\n\nFPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document,\n                                                    FPDF_FILEWRITE* pFileWrite,\n                                                    FPDF_DWORD flags);\n```\n\nFunctions in UDTs defined like that isn't something you usually see. pdfium makes you write your own write function. Other languages weren't helpful here... it seems all the ones I looked at had a built in class that somehow worked with this layout. We're not so lucky. It looked like a simple function pointer to a routine with a file write would work, and it did with one caveat: Despite the DLL's 32bit export calling convention being _stdcall, this callback had to be _cdecl, which might explain why nobody had done it in VB6 before. While there were solutions for APIs, afaik it wasn't until 2021 CDecl functions became practical with The trick's VBCDeclFix, an amazing piece of work that actually seems to finish VB6's incomplete CDecl support. \n\ntwinBASIC, of course, supports CDecl natively, so no hacks are needed.\n\nThe code opens for write the output using `CreateFile` prior to calling `FPDF_SaveAsCopy`, then fills in a copy of the UDT with `AddressOf WriteBlock` \n\n```vba\n    Private Type FPDF_FILEWRITE\n        version As Long\n        WriteBlock As LongPtr\n    End Type\n\n            Dim tWrite As FPDF_FILEWRITE\n            tWrite.version = 1\n            tWrite.WriteBlock = AddressOf WriteBlock\n\n    Private Function WriteBlock CDecl(ByVal pThis As LongPtr, ByVal pData As LongPtr, ByVal size As Long) As Long\n        If hFileOut Then\n            Dim cbRet As Long\n            Return WriteFile(hFileOut, ByVal pData, size, cbRet, vbNullPtr)\n        End If\n    End Function\n```\n\nEt voilà.\n\n------\n\n### Thanks and Notes\n Developed using pdfium builds from https://github.com/bblanchon/pdfium-binaries/releases\n\n Merge routine based on pdfium-cli: https://github.com/klippa-app/pdfium-cli\n\nAlso special thanks to tB Discord user mike webb for getting me interested in this and helping test the program while under development. mike also contributed the code for the CompressRange function in v1.2-- very good work, I was having trouble getting my head around it!\n \n\n **Command line**\\\n Command line usage:\n \nMerge: gPdfMerge.exe /i \"C:\\...\\Input1.pdf\" \"C:\\...\\Input2.pdf\" /o \"C:\\path\\Output.pdf\"\n\nAppend: gPdfMerge.exe /i \"C:\\...\\Input1.pdf\" \"C:\\...\\Input2.pdf\"\n\nAppend or merge with ranges and/or insert idx not support via command line in v1.0\n\n\n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffafalone%2Fgpdfmerge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffafalone%2Fgpdfmerge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffafalone%2Fgpdfmerge/lists"}