<script language="VB" runat="server">
Public Data As String = ""
Public Height As Byte = 25
Public WidthMultiplier As Byte = 1
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim dictEncoding As StringDictionary
Dim sbBarcodeImgs As StringBuilder
Dim strEncodedData As String
Dim I As Integer
dictEncoding = New StringDictionary()
dictEncoding.Add("0", "101001101101")
dictEncoding.Add("1", "110100101011")
dictEncoding.Add("2", "101100101011")
dictEncoding.Add("3", "110110010101")
dictEncoding.Add("4", "101001101011")
dictEncoding.Add("5", "110100110101")
dictEncoding.Add("6", "101100110101")
dictEncoding.Add("7", "101001011011")
dictEncoding.Add("8", "110100101101")
dictEncoding.Add("9", "101100101101")
dictEncoding.Add("A", "110101001011")
dictEncoding.Add("B", "101101001011")
dictEncoding.Add("C", "110110100101")
dictEncoding.Add("D", "101011001011")
dictEncoding.Add("E", "110101100101")
dictEncoding.Add("F", "101101100101")
dictEncoding.Add("G", "101010011011")
dictEncoding.Add("H", "110101001101")
dictEncoding.Add("I", "101101001101")
dictEncoding.Add("J", "101011001101")
dictEncoding.Add("K", "110101010011")
dictEncoding.Add("L", "101101010011")
dictEncoding.Add("M", "110110101001")
dictEncoding.Add("N", "101011010011")
dictEncoding.Add("O", "110101101001")
dictEncoding.Add("P", "101101101001")
dictEncoding.Add("Q", "101010110011")
dictEncoding.Add("R", "110101011001")
dictEncoding.Add("S", "101101011001")
dictEncoding.Add("T", "101011011001")
dictEncoding.Add("U", "110010101011")
dictEncoding.Add("V", "100110101011")
dictEncoding.Add("W", "110011010101")
dictEncoding.Add("X", "100101101011")
dictEncoding.Add("Y", "110010110101")
dictEncoding.Add("Z", "100110110101")
dictEncoding.Add("-", "100101011011")
dictEncoding.Add(":", "110010101101")
dictEncoding.Add(" ", "100110101101")
dictEncoding.Add("$", "100100100101")
dictEncoding.Add("/", "100100101001")
dictEncoding.Add("+", "100101001001")
dictEncoding.Add("%", "101001001001")
dictEncoding.Add("*", "100101101101")
strEncodedData = dictEncoding("*") & "0"
For I = 1 To Len(Data)
strEncodedData = strEncodedData & dictEncoding(Mid(Data, I, 1)) & "0"
Next I
strEncodedData = strEncodedData & dictEncoding("*")
sbBarcodeImgs = New StringBuilder()
For I = 1 To Len(strEncodedData)
If Mid(strEncodedData, I, 1) = "1" Then
sbBarcodeImgs.Append("<img src=""images/bar_blk.gif"" width=""" & WidthMultiplier & """ height=""" & Height & """ />")
Else
sbBarcodeImgs.Append("<img src=""images/bar_wht.gif"" width=""" & WidthMultiplier & """ height=""" & Height & """ />")
End If
Next I
litBarcode.Text = sbBarcodeImgs.ToString
End Sub
</script>
<asp:Literal ID="litBarcode" runat="server" />
Primarily the MID and dictionary usage are unfamiliar to me. Can this be completely converted to C#?
StringDictionary is just another collection class so no problem. Mid could still be used as Microsoft.VisualBasic.Mid() if you're willing to import the Visual Basic library to your C# app (nothing bad about that) or it could be rewritten fairly easily.
Edit: Actually, the VB.Net code just seems to use the Mid in the same way as you can use String.Substring so no need to use the Visual Basic library even. (I was thinking of Mid in VB6 that could be either a function or a statement, the function is similar to String.Substring but there's no real easy way to replicate it if it's the statement one but either way, doesn't matter for this code).
Have you tried using the Telerik Converter? I ran your stuff through there and didn't get any errors.
http://www.developerfusion.com/tools/convert/vb-to-csharp/
Yes. Use one of the converter tools mentioned here; only run through the code though, and not the markup parts of it.
Related
I've been scouring the interwebs for documentation leading me to be able to create lists. In doing so, I've not really been able to find any documentation that will allow me to create `lists within lists.
I've tried using the built-in macro recorder, but for whatever reason, it behaves differently when recording vs. when not recording (e.g. when I create a list item, and hit enter + tab, it doesn't create a sub list).
I've found "The Wordmeister's" MSDN post which helped me get to making a list, but lists within lists doesn't work so well for me.
Word.Paragraph p2 = doc.Paragraphs.Add();
Word.Range p2rng = p2.Range;
object oTrue = true;
object oFalse = false;
object oListName = "TreeList";
Word.ListTemplate lstTemp = doc.ListTemplates.Add(ref oTrue, ref oListName);
int l;
p2rng.ParagraphFormat.TabIndent(1);
p2rng.Text = "Rates:\r\nLevel 1\rLevel 1.1\rLevel 1.2\rLevel 2\rLevel 2.1\rLevel 2.1.1";
l = 1;
lstTemp.ListLevels[l].NumberFormat = "%" + l.ToString() + ".";
lstTemp.ListLevels[l].NumberStyle = Word.WdListNumberStyle.wdListNumberStyleArabic;
lstTemp.ListLevels[l].NumberPosition = wordApp.CentimetersToPoints(0.5f * (l - 1));
lstTemp.ListLevels[l].TextPosition = wordApp.CentimetersToPoints(0.5f * l);
l = 2;
lstTemp.ListLevels[l].NumberFormat = "%" + (l - 1).ToString() + ".%" + l.ToString() + ".";
lstTemp.ListLevels[l].NumberStyle = Word.WdListNumberStyle.wdListNumberStyleArabic;
lstTemp.ListLevels[l].NumberPosition = wordApp.CentimetersToPoints(0.5f * (l - 1));
lstTemp.ListLevels[l].TextPosition = wordApp.CentimetersToPoints(0.5f * l);
l = 3;
lstTemp.ListLevels[l].NumberFormat = "%" + (l - 2).ToString() + "%" + (l - 1).ToString() + ".%" + l.ToString() + ".";
lstTemp.ListLevels[l].NumberStyle = Word.WdListNumberStyle.wdListNumberStyleArabic;
lstTemp.ListLevels[l].NumberPosition = wordApp.CentimetersToPoints(0.5f * (l - 1));
lstTemp.ListLevels[l].TextPosition = wordApp.CentimetersToPoints(0.5f * l);
object oListApplyTo = Word.WdListApplyTo.wdListApplyToWholeList;
object oListBehavior = Word.WdDefaultListBehavior.wdWord10ListBehavior;
p2rng.ListFormat.ApplyListTemplate(lstTemp, ref oFalse, ref oListApplyTo, ref oListBehavior);
All credit to Cindy Meister for this code, it is only slightly modified to work for my use case.
The above results in the following:
Basically, how do you create multi level lists (like the following image) with lists within lists?
It's not really possible to create a "list within a list" in Word.
What you can do is put static text in the list level, in front of the dynamic number. This is the same idea as using "Chapter" or "Section" in front of the level's number, except in this case it should be a bullet symbol.
The place to define this, based on the code sample in the question, is:
lstTemp.ListLevels[l].NumberFormat = "%" + l.ToString() + ".";
As part of the NumberFormat string, in other words. For symobls this will require a conversion from unicode hex or decimal to the String data type. For example, for a solid, round bullet and an outline, round bullet for levels 1 and 2, respectively (hard-coding the list level for purposes of clarity):
char Symbol1 = (char)9679;
char Symbol2 = (char)9675;
lstTemp.ListLevels[1].NumberFormat = Symbol1.ToString() + "\t%" + l.ToString() + ".";
lstTemp.ListLevels[2].NumberFormat = Symbol2.ToString() + "\t%" + 2.ToString() + ".";
Lets try providing an answer that doesn't get deleted.
The updated list within lists example provided by #Jaberwocky can be achieved using the technique I explained in a previous post.
MS-Word: Cross reference to custom reference type
To apply the above to the specific instance required by #Jaberwock we need to amend the number formats of the list templates to which styles are linked. I'll use Word to set up the styles and required multilevel list and then include a short VBA macro which shows how to amend the list number format.
In line with the link above we first need to create our styles. The emulate the list within list example above we need to define two styles. I've defined 'ListWithinList 1' and 'ListWithinList 2'.
The key settings for these two styles are to set the outline level as 1 and 2 respectively, and to set appropriate tab stops. I've used tabs at 1,2,3 and 4 cm. Add some text to a word document and apply the styles. I've included the navigation pane in the picture below so that we can see the indentation due to the outline level of the styles
The next step is to define the multilevel list and link each level to the relevant style
Settings for outline level 1
settings for outline level 2
Our text now looks like this
I've used Word up to this point to avoid the tediousness of setting up styles and list templates programatically.
Let's now modify the format of the list numbering using a snippet of VBA.
Option Explicit
Public Sub AddTextToListNumber()
Dim my_prefix(1 To 2) As String
Dim my_index As Long
my_prefix(1) = ChrW(&H25AA) & vbTab ' small black square
my_prefix(2) = ChrW(&H25AB) & vbTab ' small white square
For my_index = 1 To 2
With ActiveDocument.Styles("ListWithinList " & CStr(my_index)).ListTemplate.ListLevels(my_index)
.numberformat = my_prefix(my_index) & .numberformat
End With
Next
End Sub
If we run the code above then the text in our document becomes
Which looks a bit ugly because of the 1cm tab stops.
If there is anything that isn't clear above please add a comment and if possible I'll update the answer.
NOTE: We didn't need the VBA code to complete setting up the list formats as we could have used appropriate Alt+XXXX keyboard sequences to insert the characters in the number format box of the multilevel list dialog box.
I am facing issue with SSRS report where I trying to generate numbers for showing sequence of filds. I am generating this data by using code in report. but it having two major issues.
Here I am able get numbers in my parent report but in sub report this numbering is not getting start from 1 it continues inside subreport and not considering parent report values.
My code is as given below. which will generate numbers like
1 dummy data
1.1 dummy data
1.2 dummy data
2 dummy data
2.1 dummy data
Dim currentValue As Double
Public Function GetCounter(ByVal iCounter As Double, ByVal incrementCounter
As Boolean) As Double
If (incrementCounter = true) Then
iCounter = (iCounter + currentValue)
currentValue = (currentValue + 0.1)
End If
Return iCounter
End Function
but with my sub report I want to generate numbers like
1 dummy data
1.1 dummy data
1.1.1 dummy data
1.1.1.1 dummy data
1.1.1.2 dummy data
1.1.2 dummy data
1.1.2.1 dummy data
1.1.2.2 dummy data
1.2 and so on.
I am not able get how can achive this with subReport.
Second issue is.
some fildes were I am getting correct numbers like from parrent report, having problem in PDF some extrea numbers are appearing in report and also numbers displaying in report and in PDF are diferent for some filds.
I am not able to get why this issue is comming and what solution I have to apply.
Pleas if any one knows solution to these issue please help me..
You can use the following custom code
Dim numbers = New Integer() {0, 0, 0, 0}
Public Function Seq(lev as Integer) As String
Select Case lev
Case 0
numbers(0) = numbers(0)+1
numbers(1) = 0
numbers(2) = 0
numbers(3) = 0
Return Cstr(numbers(0))
Case 1
numbers(1) = numbers(1)+1
numbers(2) = 0
numbers(3) = 0
Return Cstr(numbers(0)) & "." & Cstr(numbers(1))
Case 2
numbers(2) = numbers(2)+1
numbers(3) = 0
Return Cstr(numbers(0)) & "." & Cstr(numbers(1)) & "." & Cstr(numbers(2))
Case 3
numbers(3) = numbers(3)+1
Return Cstr(numbers(0)) & "." & Cstr(numbers(1)) & "." & Cstr(numbers(2)) &"." & Cstr(numbers(3))
End Select
End Function
The expression for group1 will be = Code.Seq(0), for group2 will be =Code.Seq(1), ... etc
I've inherited a Listview to perform some minor changes but I would like to improve the design in the usercontrol Class or anywhere in the Form Class 'cause I'm not happy with the default resizing mechanism of a Listview.
In the Form Class I resize the last column ("Download") like this:
ColumnDownload.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize)
The problem is that when the (default) scrollbar appears inside the listview the size of the last column is not automatically fixed/decreased so an horizontal and uneedded scrollbar automatically appears too.
Then someone could help me please to explain me how can be done this to auto-fix the size of the last column when the scrollbar appears? I'm very lost about that.
NOTE: I need to say that I'm not looking for alternative LV's such as ObjectListView.
NOTE 2: I don't show my usercontrol class 'cause I'm not performing any auto-resize improvement at the moment there, I don't know where to start.
This is my Listview as normal:
And this is the same listview filled with items:
when the (default) scrollbar appears inside the listview the size of the last column is not automatically fixed/decreased ... "default scrollbar" taken to mean the Veritical Scroll.
AutoResize is not AutoFit. It is for sizing columns based on the Header text extent or content length, not managing scrollbars and works very well. If it did automatically resize the last column, we would be angry when the last column is a small 'OK?' type column which was rendered unreadable when it was AutoFitted away.
PInvokes in a NativeMethods class; these eat scrollbars and get whether they are showing or not.
Public Const WS_VSCROLL As Integer = &H200000
Public Const WS_HSCROLL As Integer = &H100000
Friend Enum SBOrientation As Integer
SB_HORZ = &H0
SB_VERT = &H1
SB_CTL = &H2
SB_BOTH = &H3
End Enum
<DllImport("user32.dll")> _
Private Shared Function ShowScrollBar(ByVal hWnd As IntPtr,
ByVal wBar As Integer,
<MarshalAs(UnmanagedType.Bool)> ByVal bShow As Boolean
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetWindowLong(ByVal hWnd As IntPtr,
ByVal nIndex As Integer) As Integer
End Function
Friend Shared Function IsHScrollVisible(ByVal ctl As Control) As Boolean
Dim wndStyle As Integer = GetWindowLong(ctl.Handle, GWL_STYLE)
Return ((wndStyle And WS_HSCROLL) <> 0)
End Function
Friend Shared Function IsVScrollVisible(ByVal ctl As Control) As Boolean
Dim wndStyle As Integer = GetWindowLong(ctl.Handle, GWL_STYLE)
Return ((wndStyle And WS_VSCROLL) <> 0)
End Function
Friend Shared Sub ShowHideScrollBar(ByVal ctl As Control,
ByVal sb As SBOrientation, ByVal bShow As Boolean)
ShowScrollBar(ctl.Handle, sb, bShow)
End Sub
Steal xx pixels from the last column; Put the pixels back if the VScroll goes away.
Basically what happens is that ClientSizeChanged fires twice: 1) when the VScroll arrives then again a few micros later when the HScroll arrives as a result of the VScroll. So you have to process the event twice. This resizes the desired column in the first pass, and eats the HScroll in the second one. Even though the HScroll is no longer needed after Step 1, it shows up briefly if you dont remove it manually.
If an HScroll is needed due to the way you laid it out or from the user resizing columns, it will resize the last column anyway, but not eat the HScroll. The extra logic to detect when the first step is not needed is missing (you cant see that it does it, normally).
Caveats: I have no idea how or if this will work with this 3rd party theme. I dont think that the themes can modify internal scrollbars like these.
Also, this is intended for use in a subclassed LV, which I know you have already done. For others, with some reworking of references, this should also work on a form to 'push' the changes using the related events (e.g. ClientSizeChanged) even if it leaves a lot of ugly code in the form.
This also isnt wrapped in something like an IF AutoFit property test.
Private orgClient As Rectangle ' original client size for comparing
Private _VScrollWidth As Integer
Private _resizedCol As Integer = -1
Private _VScroll As Boolean = False ' persistent Scroll flags
Private _HScroll As Boolean = False
' 3rd party???
_VScrollWidth = System.Windows.Forms.SystemInformation.VerticalScrollBarWidth
Put this somewhere like ISupportInitialize.EndInit:
orgClient = Me.ClientRectangle
Sub New is not a good place for orgClient - the control hasnt been created yet. OnHandleCreated will do, but without ISupportInitialize, I would invoke a new Sub on the control to set it from Form_Load instead. This can actually be handy to have, if you want to 'restart' things after manually resizing columns then back again. For example:
' method on subclassed LV: from form load: thisLV.ResetClientSize
Public Sub ResetClientSize
orgClient = Me.ClientRectangle
End Sub
' a helper:
Private Function AllColumnsWidth() As Integer
Dim w As Integer = 0
For Each c As ColumnHeader In Columns
w += c.Width
Next
Return w
End Function
' The Meat
Protected Overrides Sub OnClientSizeChanged(ByVal e As System.EventArgs)
Dim VScrollVis As Boolean
Dim HScrollVis As Boolean
' get who is Now Showing...local vars
VScrollVis = NativeMethods.IsVScrollVisible(Me)
HScrollVis = NativeMethods.IsHScrollVisible(Me)
' width change
Dim delta As Integer = (orgClient.Width - ClientRectangle.Width)
Dim TotalWidth As Integer = AllColumnsWidth()
If (TotalWidth < ClientRectangle.Width - _VScrollWidth) And
(_resizedCol = -1) Then
Exit Sub
End If
Me.SuspendLayout()
' If VScroll IS showing, but WASNT showing the last time thru here
' ... then we are here because VScroll just appeared.
' That being the case, trim the desired column
If VScrollVis And _VScroll = False Then
' a smarter version finds the widest column and resizes THAT one
_resizedCol = Columns.Count - 1
' we have to wait for the HScroll to show up
' to remove it
Columns(_resizedCol).Width -= (delta + 1)
End If
' HScroll just appeared
If HScrollVis And (delta = _VScrollWidth) Then
' HScroll popped up, see if it is needed
If AllColumnsWidth() <= orgClient.Width Then
' no, go away foul beast !
NativeMethods.ShowHideScrollBar(Me,
NativeMethods.SBOrientation.SB_HORZ, False)
_HScroll = False ' hopefully
' allows us to set it back if the VScroll disappears
orgClient = ClientRectangle
Else
' ToDo: use this to detect when none of this is needed
_HScroll = HScrollVis
End If
End If
' If VScroll ISNOT showing, but WAS showing the last time thru here
' ...then we are here because VScroll disappeared
If VScrollVis = False And _VScroll = True Then
' put back the pixels
If _resizedCol <> -1 Then
Columns(_resizedCol).Width += (_VScrollWidth + 1)
' reset column tracker
_resizedCol = -1
' reset to new compare size
orgClient = ClientRectangle
End If
End If
_VScroll = VScrollVis
Me.ResumeLayout()
End Sub
More or less I have it done so I'll post this solution, something still wrong with the code 'cause it is not working as expected in some cases where I've tried to "play" showing and hidding the scrollbars it can hang the listview, and sure the code has unneded checks and can be improved but now I don't have more time to try to fix the related issues, if someone could help to fix this code to improve it then thankyou so much:
Dim SizeAlreadyDecreased As Boolean = False
Private Sub ElektroListView_Downloads_ClientSizeChanged(sender As Object, e As EventArgs) _
Handles ElektroListView_Downloads.ClientSizeChanged
' Retrieve all the column widths
Dim AllColumnsWidth As Integer =
(From col As ColumnHeader In CType(sender.Columns, ListView.ColumnHeaderCollection)
Select col.Width).Sum
' Fix the last column width to fill the not-used blank space when resizing the Form.
Me.ColumnDownload.Width =
Me.ColumnDownload.Width + (sender.ClientSize.Width - AllColumnsWidth) - 2
' Fix the last column width to increase or decrease the size if a VertivalScrollbar appears.
If GetScrollbars(sender) AndAlso Not SizeAlreadyDecreased Then
SizeAlreadyDecreased = True
ColumnDownload.Width -= SystemInformation.VerticalScrollBarWidth
ElseIf GetScrollbars(sender) AndAlso SizeAlreadyDecreased Then
SizeAlreadyDecreased = True
ElseIf Not GetScrollbars(sender) AndAlso SizeAlreadyDecreased Then
SizeAlreadyDecreased = False
ColumnDownload.Width += SystemInformation.VerticalScrollBarWidth
ElseIf Not GetScrollbars(sender) AndAlso Not SizeAlreadyDecreased Then
SizeAlreadyDecreased = False
End If
End Sub
Private Const WS_VSCROLL As Integer = &H200000I
Private Const WS_HSCROLL As Integer = &H100000I
Private Const GWL_STYLE As Integer = -16I
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Shared Function GetWindowLong(
ByVal hWnd As HandleRef,
ByVal nIndex As Integer
) As Integer
End Function
Public Function GetScrollbars(ByVal ctrl As Control) As ScrollBars
Dim style As Integer = GetWindowLong(New HandleRef(ctrl, ctrl.Handle), GWL_STYLE)
Dim HScroll As Boolean = ((style And WS_HSCROLL) = WS_HSCROLL)
Dim VScroll As Boolean = ((style And WS_VSCROLL) = WS_VSCROLL)
If (HScroll AndAlso VScroll) Then
Return ScrollBars.Both
ElseIf HScroll Then
Return ScrollBars.Horizontal
ElseIf VScroll Then
Return ScrollBars.Vertical
Else
Return ScrollBars.None
End If
End Function
Im struggling trying to convert this code. As well as googling for an answer and reading MSDN documentation i still cant figure this out. Ive also looked at the examples
101 for Visual Basic .Net
101 for C# .Net
Hers some C# code im trying to convert:
var asciiCredentials = (from c in credentials
select c <= 0x7f ? (byte)c : (byte)'?').ToArray();
My attempt so far:
Dim ascii = (From c In Credentials(Function(x) x= 0x7f .....)
But cant figure it out!! I think the Byte conversion is putting me off track.
Can anyone advise
Remember that Visual Basic has the IIf command that, in some respects, acts like the ternary operator.
Dim ascii = (From ch In s
Select IIf(Char.GetNumericValue(ch) < 127, Convert.ToByte(ch), Convert.ToByte("?"c))).ToArray()
You can use If in place of the conditional operator, making the code:
Dim asciiCredentials = credentials.Select(Function(x) _
If(x <= 127, Convert.ToByte(c), Convert.ToByte("?"C)))_
.ToArray();
Dim asciiCredentials = (
From c In credentials
Select If(c <= &H7f, CByte(c), AscW("?"c))).ToArray()
Dim asciiCredentials = (From c In credentials Select If(c <= &H7f, CByte(c), CByte(AscW("?"C)))).ToArray()
Taken from here:http://www.developerfusion.com/tools/convert/csharp-to-vb
They usually do pretty well converting.
I originally asked this on Adobe's forums but yet to receive any reponses.
I have to merge a set of many (100+) PDF files into a single report on a weekly basis, and so far, I have been doing the process by hand by selecting the files, right clicking, and selecting "Combine supported files in Acrobat". What I would like to do is replicate this exact same process programmatically (preferrably in Excel/VBA, but C# or Batch commands are acceptable alternatives). I currently have code that will combine pdf files, but it it does not keep the bookmark structure the same way that "Combine supported files in Acrobat" does.
In other words, say I have three files called "A.pdf", "B.pdf", and "C.pdf", and each file contains two bookmarks called "Bkmrk 1" and "Bkmrk 2". I want to programatically combine these three files into a single file that has 9 bookmarks that look like the structure below:
A
Bkmrk 1
Bkmrk 2
B
Bkmrk 1
Bkmrk 2
C
Bkmrk 1
Bkmrk 2
I at first tried automating the process via the Acrobat SDK, but from what I understand the Acrobat SDK does not allow programs to interact with the dialog box that appears when you execute the "Combine Files" menu option, so that did not work. I also tried the option to programatically insert pages from one pdf file into another, but that does not produce the bookmark structure that I am looking for, nor does it let me manipulate the bookmark heirarchy to create the bookmark structure I am looking for.
Does anyone have an idea of how to do this? Any help would be greatly appreciated!
This was pure hell to get working, so I'm happy to share what I've got. This was adapted from code I found here, and will merge files, and put bookmarks at each merge point:
Private mlngBkmkCounter As Long
Public Sub updfConcatenate(pvarFromPaths As Variant, _
pstrToPath As String)
Dim origPdfDoc As Acrobat.CAcroPDDoc
Dim newPdfDoc As Acrobat.CAcroPDDoc
Dim lngNewPageCount As Long
Dim lngInsertPage As Long
Dim i As Long
Set origPdfDoc = CreateObject("AcroExch.PDDoc")
Set newPdfDoc = CreateObject("AcroExch.PDDoc")
mlngBkmkCounter = 0
'set the first file in the array as the "new"'
If newPdfDoc.Open(pvarFromPaths(LBound(pvarFromPaths))) = True Then
updfInsertBookmark "Test Start", lngInsertPage, , newPdfDoc
mlngBkmkCounter = 1
For i = LBound(pvarFromPaths) + 1 To UBound(pvarFromPaths)
Application.StatusBar = "Merging " & pvarFromPaths(i) & "..."
If origPdfDoc.Open(pvarFromPaths(i)) = True Then
lngInsertPage = newPdfDoc.GetNumPages
newPdfDoc.InsertPages lngInsertPage - 1, origPdfDoc, 0, origPdfDoc.GetNumPages, False
updfInsertBookmark "Test " & i, lngInsertPage, , newPdfDoc
origPdfDoc.Close
mlngBkmkCounter = mlngBkmkCounter + 1
End If
Next i
newPdfDoc.Save PDSaveFull, pstrToPath
End If
ExitHere:
Set origPdfDoc = Nothing
Set newPdfDoc = Nothing
Application.StatusBar = False
Exit Sub
End Sub
The insert-bookmark code... You would need to array your bookmarks from each document, and then set them
Public Sub updfInsertBookmark(pstrCaption As String, _
plngPage As Long, _
Optional pstrPath As String, _
Optional pMyPDDoc As Acrobat.CAcroPDDoc, _
Optional plngIndex As Long = -1, _
Optional plngParentIndex As Long = -1)
Dim MyPDDoc As Acrobat.CAcroPDDoc
Dim jso As Object
Dim BMR As Object
Dim arrParents As Variant
Dim bkmChildsParent As Object
Dim bleContinue As Boolean
Dim bleSave As Boolean
Dim lngIndex As Long
If pMyPDDoc Is Nothing Then
Set MyPDDoc = CreateObject("AcroExch.PDDoc")
bleContinue = MyPDDoc.Open(pstrPath)
bleSave = True
Else
Set MyPDDoc = pMyPDDoc
bleContinue = True
End If
If plngIndex > -1 Then
lngIndex = plngIndex
Else
lngIndex = mlngBkmkCounter
End If
If bleContinue = True Then
Set jso = MyPDDoc.GetJSObject
Set BMR = jso.bookmarkRoot
If plngParentIndex > -1 Then
arrParents = jso.bookmarkRoot.Children
Set bkmChildsParent = arrParents(plngParentIndex)
bkmChildsParent.createchild pstrCaption, "this.pageNum= " & plngPage, lngIndex
Else
BMR.createchild pstrCaption, "this.pageNum= " & plngPage, lngIndex
End If
MyPDDoc.SetPageMode 3 '3 — display using bookmarks'
If bleSave = True Then
MyPDDoc.Save PDSaveIncremental, pstrPath
MyPDDoc.Close
End If
End If
ExitHere:
Set jso = Nothing
Set BMR = Nothing
Set arrParents = Nothing
Set bkmChildsParent = Nothing
Set MyPDDoc = Nothing
End Sub
To use:
Public Sub uTest_pdfConcatenate()
Const cPath As String = "C:\MyPath\"
updfConcatenate Array(cPath & "Test1.pdf", _
cPath & "Test2.pdf", _
cPath & "Test3.pdf"), "C:\Temp\TestOut.pdf"
End Sub
You might need to consider a commercial tool such as Aspose.Pdf.Kit to get the level of flexibility you're after. It does support file concatenation and bookmark manipulation.
There's a 30 day unlimited trial so you can't really lose out other than time if it doesn't work for you.
Use iText# (http://www.itextpdf.com/). imho it is one of the best PDF-tools around. A code to do (approximately) what you want can be found here http://java-x.blogspot.com/2006/11/merge-pdf-files-with-itext.html
Do not worry that all examples talk about Java, the classes and functions are the same in .NET
hth
Mario
Docotic.Pdf library can merge PDF files while maintaining outline (bookmarks) structure.
There is nothing special should be done. You just append all documents one after another and that's all.
using (PdfDocument pdf = new PdfDocument())
{
string[] filesToMerge = ...
foreach (string file in filesToMerge)
pdf.Append(file);
pdf.Save("merged.pdf");
}
Disclaimer: I work for Bit Miracle, vendor of the library.
The Acrobat SDK does let you create and read bookmarks. Check your SDK API Reference for:
PDDocGetBookmarkRoot()
PDBookmark* (AddChild, AddNewChild, GetNext, GetPrev... lots of functions in there)
If the "combine files" dialog doesn't give you the control you need, make your own dialog.