I've got some code that builds a PDF from an HTML template, then attaches several other PDFs to make one big PDF using abcPDF 7.
All this works fine and dandy -- however, I'd like to make some links in the HTML portion of the PDF to jump down to one of the several attached PDFs.
I tried creating links and anchors using the technique referenced here, by putting the
Link to another page
link in the HTML, then putting the anchor
<div><a name="elementId">A div that's on another page</a></div>
as an added-on paste-over on the top of the first page of the PDF I wanted to jump to.
I can see the text of the anchor just fine, and the link to it is blue, but it doesn't do anything.
As the next attempt, I've created bookmarks that work as well. Can someone point me in the direction to go back and adjust the links in the HTML portion to use them to jump to the bookmarks?
I apologize in advance for a lack of code, and I'm not asking for any code now.. I'd just like a more general way to go about it, like "try something like this." I'm not having much luck finding anything that is close to what I'm trying to do, not even on WebSuperGoo's website.
This method has worked for me in the latest ABCpdf version (9) Add a bookmark to each page in your document:
For i = 1 to pdf.PageCount
pdf.PageNumber = i
pdf.AddBookmark("Page " & i, True)
Next
Then where you want to insert a link you can reference the bookmark - in this case we create a table of contents by looping through each bookmark we've created:
For Each bm As Bookmark In pdf.Bookmark
toc &= "<Font annots='goto:" + bm.Page.PageNumber.ToString() + "'>" & bm.Title & "</Font><br>"
Next
pdf.AddHtml(toc)
The Websupergoo team supplied me with some example code and that's what this is based off of - so thanks to them!
Related
I'm exploring different options for .NET PDF libraries. One of my requirements is to place a box at the bottom of the first page and if any of the content reaches the box, it should overflow onto the next page.
For example:
Shown above, paragraph 7 would normally take up some of the space that's occupied by the "reserved" area. Instead, the part that would have taken up that space is shifted to the next page.
That image was achieved using Gembox.Document by adding the box as a footer element that only renders on the first page. However, in iText7, the examples I've seen for adding a footer (such as this one), places the content as a floating element that renders over the existing content and does not affect the layout/flow of the rest of the document.
I also tried adding a paragraph on the PageEnd event handler without the canvas (snippet below), but instead of adding it to the specified page, it's added to the end of the entire document.
public void HandleEvent(Event evt)
{
var docEvent = (PdfDocumentEvent)evt;
var page = docEvent.GetPage();
int pageNum = docEvent.GetDocument().GetPageNumber(page);
if (pageNum == 1)
{
doc.Add(new Paragraph("Testing a thing"));
}
}
Is the type of effect I'm looking for something that I can replicate using iText7?
I believe you can combine the concepts of https://github.com/itext/i7ns-samples/blob/develop/itext/itext.samples/itext/samples/sandbox/acroforms/AddExtraTable.cs and https://github.com/itext/i7ns-samples/blob/develop/itext/itext.samples/itext/samples/sandbox/events/TextFooter.cs to achieve what you need.
The idea is as follows:
reserve place for your box by making iText give the document's renderer less space for the first page
fill this box with a help of iText's end page events
Another option was suggested in How can I insert an element to the bottom of a specific page in iText7? : you can temporary call Document#setBottomMargin , since elements added via Document#add will not be placed on margins. Then, once the first page is layouted, you can set the initial margins again. This option, however, requires understanding of you layout flow, since the margins should be set only after the content of the first page is layouted.
One more suggestion: althouth event functionality is rather flexible and useful, it seems like using a sledgehammer to crack a nut. You need to call Canvas#ShowTextAligned, which could be done without any event handling. So ideally I would prefer to do the following:
handle page's layout area via an extension of DocumentRenderer
Calling Canvas#ShowTextAligned to fill the reserved box.
As you said, you are exploring different .NET PDF libraries. So I would advise PDFFlow library, which does exactly what you need.
If you have a footer, main document flow will take the rest of page area and will be automatically continued at the next page without overlaying footer.
DocumentBuilder.New()
.AddSection()
.AddParagraph("long text")
.ToSection()
.AddFooterToBothPages(40)
.AddParagraph("this a footer set for each page of this section")
.ToDocument()
.Build("result.pdf");
Here is a tutorial with code examples of using headers, footers, left/right repeating areas: AddingRepeatingArea tutorial.
Hope, this will help you :)
What is the code for delimiting pages in RTF?
I am using:
\page\par
It works but this code puts a break-line at the top of each new page. So all my pages except first page start with a break line. How can I erase this break-line?
The '\par' is representing a paragraph and as I see like in HTML this parahraph is delimited by the rest of the content through spaces.
In RTF, \par represents a paragraph break. \page alone will suffice to create a page break without a blank line after it.
I'm using Word 2016 to view the RTF, and \page alone simply does not generate a page break. But \page\par does. I don't know why. It has been driving me crazy for a few hours.
I finally found a hack: set the font size to zero on the extraneous \par, then set it back when you are done.
So if you are working with font size 10, the code will be \page\fs0\par\fs20. Remember that the fs size is double the font size.
I totally hate this. But it is the only thing I've found that actually works. If anyone finds something better, please post it.
I am taking a document into an html page to show the user with .Net libraries' help. I am using LoadHtml method under HtmlAgilityPack. But when i use that method to fill the html, it does not show the tab(ascii=09) characters right. So i use it like:
doc.LoadHtml("<pre>" + pContent + "</pre>");
But when i do that then i can not add any picture links or pictures to the html page. normally before i use "< pre >", the user was able to add links. The code below was running behind.
string text = string.Format(#"<img src='{0}' />", thepicturelink);
My problem is that i want to make my page both could be added links(pictures) and looks proper with tab character. I could not find any solution for that in here, msdn, socialmsdn, codeproject or google. Does anyone have a solution for that problem? Thank for helps. Best regards.
C# Visual Studio 2010
I am loading a complex html page into a webbrowser control. But, I don't have the ability to modify the webpage. I want to click a link on the page automatically from the windows form. But, the ID appears to be randomly generated each time the page is loaded (so I believe referencing the ID will not work).
This is the content of the a href link:
<a
id="u_lp_id_58547"
href="javascript:void(0)"
class="SGLeftPanelText" onclick="setStoreParams('cases;212', 212); window.leftpanel.onClick('cases_ss_733');return false; ">
My Assigned</a>
Is the anyway to click the link from C#?
Thanks!
UPDATE:
I feel like this is close but it is just not working:
HtmlElementCollection links = helpdeskWebBrowser.Document.Window.Frames["main_pending_events_frame"].Document.GetElementsByTagName("a");
MessageBox.Show(links.Count.ToString());
I have tried plugging in every single frame name and tried both "a" and "A" in the TagName field but just have not had any luck. I can just not find any links; the message box is always 0. What am I missing?
Something like this should work:
HtmlElement link = webBrowser.Document.GetElementByID("u_lp_id_58547")
link.InvokeMember("Click")
EDIT:
Since the IDs are generated randomly, another option may be to identify the links by their InnerText; along these lines.
HtmlElementCollection links = webBrowser.Document.GetElementsByTagName("A");
foreach (HtmlElement link in links)
{
if (link.InnerText.Equals("My Assigned"))
link.InvokeMember("Click");
}
UPDATE:
You can get the links within an IFrame using:
webBrowser.Document.Window.Frames["MyIFrame"].Document.GetElementsByTagName("A");
Perhaps you will have to isolate the link ID value using more of the surrounding HTML context as a "target" and then extract the new random ID.
In the past I have used the "HtmlAgilityPack" to easily parse "screen-scraped" HTML to isolate areas of interest within a page - this library seems to be easy to use and reliable.
i want create small web browser , tiny and fast
but i have problem ,
let me explain :
1 - user enter site : google.com
2 - c# program get google.com
3 - find <td nowrap="" align="center">
4 - in web browser only show that area
i dont know where i must start ,
thanks
Ok, I'm going to try answer your question, but I am deciphering as well.
Create a WebBrowser control on your form. (2.0 is fine for what you need) and .Navigate("http://www.google.com");
Get the source code from the Document. You can do this as follows: string source = _WebBrowser.Document.Body.OuterHtml;
Use string manipulation to get to the area on the page you need. For instance .SubString() functions
Save the text into a file, or stream and load it into the WebBrowser control, or replace the pages Document HTML with just the HTML you are wanting to show.
Okay! Looking at the comment it seems you want to request for a page using c# and show only one part of the page. In your case its that specific <td> . Please correct me if I am wrong.
Other than what Kyle has mentioned. Check out HTML agility Pack. It might be of interest to you.