I am trying to accomplish a simple task of merging PDF files to one PDF. And I want the resulting PDF file to have Bookmarks to each file from the filename. And preferably i would like to have a free solution for this.
I am on a windows system and want to execute this from either command line or even better from MSSQL.
The thing is that i will create PDF files of orders from an ERP system with Crystal Reports. An stored procedure will create these PDF files. After that i want to take selected PDFs and create a new merged PDF of those and the merged PDF should have each order number (from the filename) as a bookmark. So that you easily can jump to an order number if you are searching for a specific one.
And as I said preferably free solutions, if not available I am ready to code my own merge program in for example C# or similar.
I think you would need Adobe Acrobat for this, at a bare minimum. Or, if you don't have that and you don't want to pay for it, you can convert all PDFs to TXT files, and merge all TXT files. This sounds a bit cumbersome, but actually, the easiest thing to do . . . maybe . . . is to convert all those TXT files into Excel files, and merge those. That shouldn't be hard at all. Here is a script to convert all TXT files into Excel files.
Private Declare Function SetCurrentDirectoryA Lib _
"kernel32" (ByVal lpPathName As String) As Long
Public Function ChDirNet(szPath As String) As Boolean
'based on Rob Bovey's code
Dim lReturn As Long
lReturn = SetCurrentDirectoryA(szPath)
ChDirNet = CBool(lReturn <> 0)
End Function
Sub Get_TXT_Files()
'For Excel 2000 and higher
Dim Fnum As Long
Dim mysheet As Worksheet
Dim basebook As Workbook
Dim TxtFileNames As Variant
Dim QTable As QueryTable
Dim SaveDriveDir As String
Dim ExistFolder As Boolean
'Save the current dir
SaveDriveDir = CurDir
'You can change the start folder if you want for
'GetOpenFilename,you can use a network or local folder.
'For example ChDirNet("C:\your_path_here\")
'It now use Excel's Default File Path
ExistFolder = ChDirNet("C:\your_path_here\\Text\")
If ExistFolder = False Then
MsgBox "Error changing folder"
Exit Sub
End If
TxtFileNames = Application.GetOpenFilename _
(filefilter:="TXT Files (*.txt), *.txt", MultiSelect:=True)
If IsArray(TxtFileNames) Then
On Error GoTo CleanUp
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Add workbook with one sheet
Set basebook = Workbooks.Add(xlWBATWorksheet)
'Loop through the array with txt files
For Fnum = LBound(TxtFileNames) To UBound(TxtFileNames)
'Add a new worksheet for the name of the txt file
Set mysheet = Worksheets.Add(After:=basebook. _
Sheets(basebook.Sheets.Count))
On Error Resume Next
mysheet.Name = Right(TxtFileNames(Fnum), Len(TxtFileNames(Fnum)) - _
InStrRev(TxtFileNames(Fnum), "\", , 1))
On Error GoTo 0
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;" & TxtFileNames(Fnum), Destination:=Range("A1"))
.TextFilePlatform = xlWindows
.TextFileStartRow = 1
'This example use xlDelimited
'See a example for xlFixedWidth below the macro
.TextFileParseType = xlDelimited
'Set your Delimiter to true
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
'Set the format for each column if you want (Default = General)
'For example Array(1, 9, 1) to skip the second column
.TextFileColumnDataTypes = Array(1, 9, 1)
'xlGeneralFormat General 1
'xlTextFormat Text 2
'xlMDYFormat Month-Day-Year 3
'xlDMYFormat Day-Month-Year 4
'xlYMDFormat Year-Month-Day 5
'xlMYDFormat Month-Year-Day 6
'xlDYMFormat Day-Year-Month 7
'xlYDMFormat Year-Day-Month 8
'xlSkipColumn Skip 9
' Get the data from the txt file
.Refresh BackgroundQuery:=False
End With
ActiveSheet.QueryTables(1).Delete
Next Fnum
'Delete the first sheet of basebook
On Error Resume Next
Application.DisplayAlerts = False
basebook.Worksheets(1).Delete
Application.DisplayAlerts = True
On Error GoTo 0
CleanUp:
ChDirNet SaveDriveDir
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End If
End Sub
Related
I wrote a code where I want a user to select multiple files that code will loop through.
I can't get the loop to work as I am not defining the name right.
Sub RFPDataimporttest() 'select multiple files
Dim Files As Workbook
Dim Fname As Variant
Dim SrcWbk As Workbook
Dim DestWbk As Workbook
Dim i As Integer
Set DestWbk = ThisWorkbook
'choose files and define them as array
Fname = Application.GetOpenFilename(FileFilter:="Excel Files (*.xls*), *.xls*", Title:="Select alla RFP filer från leverantörer", MultiSelect:=True)
If IsArray(Fname) Then
For i = LBound(Fname) To UBound(Fname)
'this where i have a problem. how do i open each file in an array?
Set SrcWbk = Workbooks.Open(Fname)
SrcWbk.Sheets("1. General Information").Range("L8").Copy
With DestWbk.Worksheets("Sheet1").Cells(2, Columns.Count).End(xlToLeft).Offset(-1, 1)
.PasteSpecial Paste:=xlPasteColumnWidths
.PasteSpecial Paste:=xlPasteValues
End With
SrcWbk.Sheets("2. Product information").Range("Z1:AB91").Copy
With DestWbk.Worksheets("Sheet1").Cells(2, Columns.Count).End(xlToLeft).Offset(0, 1)
.PasteSpecial Paste:=xlPasteColumnWidths
.PasteSpecial Paste:=xlPasteValues
End With
SrcWbk.Close False
Next i
End If
End Sub
The result is an array - you are already checking that and looping over it. Simply use i as index:
Set SrcWbk = Workbooks.Open(Fname(i))
(note that the result is even an array when user selects only one file, so code will work for that case also)
Could someone tell me if it is possible for a user to input two seperate dates into input boxes and then search a folder for files with (ideally) create dates that fall between the input dates?
I can do a search through files in a folder fine but the number of files is increasing every day and the time to run a search through all of them is getting longer. I'm hopeing that if the user can select a date range then this will cut down the time to run.
If that isn't possible at all is it possible to set a macro to search through files in a folder STARTING with the most recently created and then working back from there?
Sub UKSearch()
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Search function to find specific consignment number from multiple intake sheets'
'Used by Traffic Office '
'Created by *********** 11/03/14 Password to unlock = ********* '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim FSO As Object 'FileSystemObject
Set FSO = CreateObject("scripting.filesystemobject")
Dim Directory As String
Dim FileName As String
Dim varCellvalue As Long
Application.ScreenUpdating = False
MsgBox ("This may take a few minutes")
'value to be searched
varCellvalue = Range("D13").Value
'Change the directory below as needed
Directory = "\\*******\shared$\Common\Returns\*********\"
If Right(Directory, 1) <> "\" Then
Directory = Directory & "\"
End If
'Search for all files in the directory with an xls* file type.
FileName = Dir(Directory & "*.xls*")
''''''''''''''''''''''''
'Opens, searches through and closes each file
Do While FileName <> ""
OpenFile = Directory & FileName
Workbooks.Open (OpenFile)
Workbooks(FileName).Activate
'Count through all the rows looking for the required number
ActiveWorkbook.Sheets("UK Scan Sheet").Activate
LastRow = Range("B65536").End(xlUp).Row
intRowCount = LastRow
Range("B1").Select
For i = 1 To intRowCount
'If the required number is found then select it and stop the search
If ActiveCell.Value = varCellvalue Then
GoTo Finish
Else
End If
ActiveCell.Offset(1, 0).Select
Next i
Workbooks(FileName).Close
FileName = Dir
OpenFile = ""
Loop
''''''''''''''''''''''''''
Finish:
Application.ScreenUpdating = False
End Sub
Add to your dim section:
Dim oFile
Before your loop add:
Set oFile = CreateObject("Scripting.FileSystemObject")
In your loop before you open the file add an if statement:
if oFile.getFile(Directory & FileName).DateCreated >= EarliestDate and oFile.getFile(Directory & FileName).DateCreated <= LatestDate
You can also use oFile.getFile(Directory & FileName).DateLastModified - if you want to use the last change date of file instead of creation date.
I have one file which is database and contain data of all student from different classes. I want excel to make class wise files by copying data from database to new file... I am using below mention codes and these are working perfect but it only coping data till Column G and now data has extended to Column Z and its not working give me run time error.
"Note Column B tittle Class" i.e Tittle of new saved file
Sub proSaveDateClasswise()
Range("I1").Value = "Class"
Columns("B:B").AdvancedFilter Action:=xlFilterCopy, copyToRange:=Columns( _
"I:I"), unique:=True
Range("J1").Value = "Class"
Dim cell As Range
Dim curPath As String
curPath = ActiveWorkbook.Path & "\Extracted Files\\"
If Len(Dir(curPath, vbDirectory)) = 0 Then
MkDir (curPath)
End If
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each cell In Range("I:I")
If cell.Value <> "Branch" And cell.Value <> "" Then
Range("J2").Value = cell.Value
Range("A:G").AdvancedFilter Action:=xlFilterCopy, _
criteriarange:=Range("J1:J2"), copyToRange:=Range("L:R"), unique:=False
Range(Range("L1:R1"), Range("L1:R1").End(xlDown)).Copy
Workbooks.Add
ActiveSheet.Paste
ActiveWorkbook.SaveAs Filename:=curPath & cell.Value & ".xlsx", _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
ActiveWindow.Close
Range(Range("L1:R1"), Range("L1:R1").End(xlDown)).ClearContents
End If
Next cell
Columns("I:R").Delete
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
I think the main issue here before we go any further is that your current macro uses some columns beyond G in order to select unique classes. That means the whole code would have to be rewritten for it to work as you expect. I suggest you provide some input and output files with dummy data to work on.
What's the easiest way to import 500 XLS files all with the same structure but each one with its own unique Sheet name ...into SQL Server?
Alternatively, I have combined ALL XLS files into a single XLS file but each sheet name is now unique within the XLS file.
I found these 2 VBA that helped me complete the job.
The 1st one combines all XLS in one directory into a single XLS and creates a unique Worksheet for each XLS file.
Sub Merge_Multiple_XLS_Into_WorkSheets()
Path = "C:\Folder\"
Filename = Dir(Path & "*.xls")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
For Each Sheet In ActiveWorkbook.Sheets
Sheet.Copy After:=ThisWorkbook.Sheets(1)
Next Sheet
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub
The 2nd one combining all Sheets into a single one
Sub Merge_Sheets_Into_One()
Const sRANGE = "A2:Z100"
Dim iSheet, iTargetRow As Long, oCell As Object, bRowWasNotBlank As Boolean
Dim iTop, iLeft, iBottom, iRight As Long
Sheets(1).Select: Sheets.Add
Sheets(1).Select
Cells.Select
Selection.Clear
bRowWasNotBlank = True
For iSheet = 2 To ThisWorkbook.Sheets.Count: DoEvents
For Each oCell In Sheets(iSheet).Range(sRANGE).Cells: DoEvents
If oCell.Column = 1 Then
If bRowWasNotBlank Then iTargetRow = iTargetRow + 1
bRowWasNotBlank = False
End If
If oCell.MergeCells Then
bRowWasNotBlank = True
If oCell.MergeArea.Cells(1).Row = oCell.Row Then
If oCell.MergeArea.Cells(1).Column = oCell.Column Then
Sheets(1).Cells(iTargetRow, oCell.Column) = oCell
iTop = iTargetRow
iLeft = oCell.Column
iBottom = iTop + oCell.MergeArea.Rows.Count - 1
iRight = iLeft + oCell.MergeArea.Columns.Count - 1
Sheets(1).Range(Cells(iTop, iLeft), Cells(iBottom, iRight)).MergeCells = True
End If
End If
End If
If Len(oCell) Then bRowWasNotBlank = True
Sheets(1).Cells(iTargetRow, oCell.Column) = oCell
Next oCell
Next
Sheets(1).Activate
End Sub
...and after running these 2 VBS scripts, it's just a matter of running Import Data wizard inside from the MS-SQL Management Studio.
Hope this helps...
I'm converting a database from access to a sql backend access front end. The database has embedded pdf documents which end up getting stored as [image] data by SQL server's data import tools.
My problem is that I want the users to be able to open the pdf file by clicking the pdf icon in a report created in access.
Can this be done with VBA or is there an easier way? I'm at a total loss on how to make this happen.
Thanks for the answer!
I edited the BlobToFile function to strip out the ole header since adobe couldn't read the file (evince could and so could mac preview)
I was able to do what I wanted like this:
Private Sub PDFDocument_Click()
Call BlobToFile("C:\db\MyPDFFile.pdf", Me.PDFDocument)
If Dir("C:\db\MyPDFFile.pdf") <> "" Then
FollowHyperlink ("C:\db\MyPDFFile.pdf")
End If
End Sub
'Function: BlobToFile - Extracts the data in a binary field to a disk file.
'Parameter: strFile - Full path and filename of the destination file.
'Parameter: Field - The field containing the blob.
'Return: The length of the data extracted.
Public Function BlobToFile(strFile As String, ByRef Field As Object) As Long
On Error GoTo BlobToFileError
Dim nFileNum As Integer
Dim abytData() As Byte
Dim abytParsedData() As Byte
Dim copyOn As Boolean
Dim copyIndex As Long
BlobToFile = 0
nFileNum = FreeFile
copyOn = False
copyIndex = 0
Open strFile For Binary Access Write As nFileNum
abytData = Field
ReDim abytParsedData(UBound(abytData))
For i = LBound(abytData) To UBound(abytData) - 1
If copyOn = False Then
If Chr(abytData(i)) = "%" And Chr(abytData(i + 1)) = "P" And Chr(abytData(i + 2)) = "D" And Chr(abytData(i + 3)) = "F" Then
copyOn = True
End If
End If
If copyOn = True Then
abytParsedData(copyIndex) = abytData(i)
copyIndex = copyIndex + 1
End If
Next
Put #nFileNum, , abytParsedData
BlobToFile = LOF(nFileNum)
BlobToFileExit:
If nFileNum > 0 Then Close nFileNum
Exit Function
BlobToFileError:
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, _
"Error writing file in BlobToFile"
BlobToFile = 0
Resume BlobToFileExit
End Function
If I understand what you are trying to do, you basically want Adobe Reader to open an in-memory pdf file "object". This isn't possible. You'll need to write the pdf file out to the system hard drive and then open it from there. You can somewhat achieve what you're asking by either using the computers Temp folder or else managing the files/folder yourself. For example, you could possibly cleanup your PDF file folder every time the application opens.
Here's some code to help you do what you're trying to do. This code does not handle anything to do with creating folders, generating file names, checking to see if the file already exists, etc. I'm assuming that you'll be able to handle that. My code in Command1_Click assumes that you're using SQL Server with ODBC linked tables.
I'm using FollowHyperlink here but I highly recommend that you use Allen Browne's GoHyperlink function instead to open files. You'll probably have security errors with FollowHyperlink.
Private Sub Command1_Click()
Dim r As DAO.Recordset, sSQL As String
sSQL = "SELECT ID, BlobField FROM MyTable"
Set r = CurrentDb.OpenRecordset(sSQL, dbOpenDynaset, dbSeeChanges)
If Not (r.EOF And r.BOF) Then
Call BlobToFile("C:\MyPDFFile.pdf", r("BlobField"))
If Dir("C:\MyPDFFile.pdf") <> "" Then
FollowHyperlink("C:\MyPDFFile.pdf")
End If
End If
r.Close
Set r = Nothing
End Sub
'Function: BlobToFile - Extracts the data in a binary field to a disk file.
'Parameter: strFile - Full path and filename of the destination file.
'Parameter: Field - The field containing the blob.
'Return: The length of the data extracted.
Public Function BlobToFile(strFile As String, ByRef Field As Object) As Long
On Error GoTo BlobToFileError
Dim nFileNum As Integer
Dim abytData() As Byte
BlobToFile = 0
nFileNum = FreeFile
Open strFile For Binary Access Write As nFileNum
abytData = Field
Put #nFileNum, , abytData
BlobToFile = LOF(nFileNum)
BlobToFileExit:
If nFileNum > 0 Then Close nFileNum
Exit Function
BlobToFileError:
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, _
"Error writing file in BlobToFile"
BlobToFile = 0
Resume BlobToFileExit
End Function