Wondered if it's possible to iterate through the pages held in the pages library and determine the page layout being used by each page? any c# code examples appreciated.
Many thanks in advance
You can get a reference to a PublishingWeb object and throught that the PublishingPage object which has a Layout property.
Below I have butchered the two pages example code to get something close to what you need.
using (SPWeb web = site.OpenWeb(HttpUtility.UrlDecode(webUri.AbsolutePath)))
{
PublishingWeb pWeb = null;
if (!web.Exists || !PublishingWeb.IsPublishingWeb(web))
{
return;
}
pWeb = PublishingWeb.GetPublishingWeb(web);
PublishingPageCollection publishingPages = publishingWeb.GetPublishingPages();
foreach (PublishingPage publishingPage in publishingPages)
{
//do something here with publishingPage.Layout
}
}
Related
I'm trying to add a page number to the bottom of the page, which doesn't seem to work as expected.
Currently i'm using this:
<span class="page"></span>/<span class="topage"></span>
The problem with this solution is that it doesn't count the cover as a page.
So a 7 page PDF "has" 6 pages according to my code.
I'm looking for a way to include the Cover as a page, so the number is correct.
Currently i'm looking into some JS to manipulate it afterwards, but there have to me some "official" solution?
Solved using javascript. :)
If anyone are looking for the solution here you go:
var x=window.location.search.substring(1).split('&');
for (var i in x) {
var z=x[i].split('=',2);
vars[z[0]] = unescape(z[1]);
}
var pageNumberStart = parseInt(vars.page);
var pageNumberEnd = parseInt(vars.topage);
if (pageNumberStart != null && pageNumberEnd != null) {
document.getElementById('page').innerHTML = pageNumberStart + 1;
document.getElementById('topage').innerHTML = pageNumberEnd + 1;
}
Maybe someone got the official way to do it? :D
I'm trying to access a page in Word by it's name or number. I thought I was going in the right direction but there doesn't seem to be a page.name or page.number property. The issue is in my if statement where I'm trying to say if there is a page named Page 4 Content then select it.
var wordApplication = (word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
string path = CommonMethods.getFile(fileName);
myDoc = wordApplication.Documents.Open(path);
wordApplication.Visible = true;
wordApplication.WindowState = word.WdWindowState.wdWindowStateMaximize;
word.Pages pages = myDoc.ActiveWindow.ActivePane.Pages;
foreach (word.Page p in pages )
{
if (p.)
{
}
}
As you already mentioned there is no number or name property on the page object.
In order to get the page number you have to access the Information property of a Range or Selection object on that page.
In addition to that I recommend to study the article Selecting or referring to a page in the Word object model by Shauna Kelly. In her article she explains in detail why it is often not a good idea to rely on the page object for automated document processing. The reason for that is that Word uses a flow layout instead of a fixed layout. In order to determine the current page rendering Word has to talk to the current printer driver. This means that your page breaks may vary depending on your printer.
I ended up doing the following and it works like a charm.
object What = Microsoft.Office.Interop.Word.WdGoToItem.wdGoToPage;
object Which = Microsoft.Office.Interop.Word.WdGoToDirection.wdGoToAbsolute;
object Miss = System.Reflection.Missing.Value;
word.Pages pages = doc.ActiveWindow.ActivePane.Pages;
for (int i = 0; i < pages.Count; i++)
{
if (i == pageNumber)
{
doc.Application.Selection.GoTo(ref What, ref Which, pageNumber, ref Miss);
}
}
}
Background Info: I'm using an ItemCheckedIn receiver in SharePoint 2010, targeting .NET 3.5 Framework. The goal of the receiver is to:
Make sure the properties (columns) of the page match the data in a Content Editor WebPart on the page so that the page can be found in a search using Filter web parts. The pages are automatically generated, so barring any errors they are guaranteed to fit the expected format.
If there is a mismatch, check out the page, fix the properties, then check it back in.
I've kept the receiver from falling into an infinite check-in/check-out loop, although right now it's a very clumsy fix that I'm trying to work on. However, right now I can't work on it because I'm getting a DisconnectedContext error whenever I hit the UpdatePage function:
public override void ItemCheckedIn(SPItemEventProperties properties)
{
// If the main page or machine information is being checked in, do nothing
if (properties.AfterUrl.Contains("home") || properties.AfterUrl.Contains("machines")) return;
// Otherwise make sure that the page properties reflect any changes that may have been made
using (SPSite site = new SPSite("http://san1web.net.jbtc.com/sites/depts/VPC/"))
using (SPWeb web = site.OpenWeb())
{
SPFile page = web.GetFile(properties.AfterUrl);
// Make sure the event receiver doesn't get called infinitely by checking version history
...
UpdatePage(page);
}
}
private static void UpdatePage(SPFile page)
{
bool checkOut = false;
var th = new Thread(() =>
{
using (WebBrowser wb = new WebBrowser())
using (SPLimitedWebPartManager manager = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
// Get web part's contents into HtmlDocument
ContentEditorWebPart cewp = (ContentEditorWebPart)manager.WebParts[0];
HtmlDocument htmlDoc;
wb.Navigate("about:blank");
htmlDoc = wb.Document;
htmlDoc.OpenNew(true);
htmlDoc.Write(cewp.Content.InnerText);
foreach (var prop in props)
{
// Check that each property matches the information on the page
string element;
try
{
element = htmlDoc.GetElementById(prop).InnerText;
}
catch (NullReferenceException)
{
break;
}
if (!element.Equals(page.GetProperty(prop).ToString()))
{
if (!prop.Contains("Request"))
{
checkOut = true;
break;
}
else if (!element.Equals(page.GetProperty(prop).ToString().Split(' ')[0]))
{
checkOut = true;
break;
}
}
}
if (!checkOut) return;
// If there was a mismatch, check the page out and fix the properties
page.CheckOut();
foreach (var prop in props)
{
page.SetProperty(prop, htmlDoc.GetElementById(prop).InnerText);
page.Item[prop] = htmlDoc.GetElementById(prop).InnerText;
try
{
page.Update();
}
catch
{
page.SetProperty(prop, Convert.ToDateTime(htmlDoc.GetElementById(prop).InnerText).AddDays(1));
page.Item[prop] = Convert.ToDateTime(htmlDoc.GetElementById(prop).InnerText).AddDays(1);
page.Update();
}
}
page.CheckIn("");
}
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
From what I understand, using a WebBrowser is the only way to fill an HtmlDocument in this version of .NET, so that's why I have to use this thread.
In addition, I've done some reading and it looks like the DisconnectedContext error has to do with threading and COM, which are subjects I know next to nothing about. What can I do to prevent/fix this error?
EDIT
As #Yevgeniy.Chernobrivets pointed out in the comments, I could insert an editable field bound to the page column and not worry about parsing any html, but because the current page layout uses an HTML table within a Content Editor WebPart, where this kind of field wouldn't work properly, I'd need to make a new page layout and rebuild my solution from the bottom up, which I would really rather avoid.
I'd also like to avoid downloading anything, as the company I work for normally doesn't allow the use of unapproved software.
You shouldn't do html parsing with WebBrowser class which is part of Windows Forms and is not suited for web as well as for pure html parsing. Try using some html parser like HtmlAgilityPack instead.
I am using the GeckoFX 22 c# web browser control but cannot manage to access tags within an iframe. When I check the gecko innerhtml it seems that although the iframe tag shows in the html, the contents of it do not.
This is the code I used to get the inner html of the browser control which just shows the iframe tag as empty (when it should have another doc inside of it):
GeckoHtmlElement element = null;
var geckoDomElement = webBrowser.Document.DocumentElement;
if (geckoDomElement is GeckoHtmlElement)
{
element = (GeckoHtmlElement)geckoDomElement;
var innerHtml = element.InnerHtml;
}
Previously I used code similar to the code below to access individual elements which works fine:
GeckoDocument checkDoc = (GeckoDocument)webBrowser.Window.Document;
var x = (checkDoc.GetElementsByTagName("a").Where(b => b.Id == "ipt-form-format-aside").First());
I am able to get individual elements and change their values/trigger events etc without problems with the main html document but anything in an iframe is impossible to get the elements of. I think perhaps the Iframe has not been loaded yet or something like that. Is there a way to force the control to wait for the I frame to load before attempting to access its elements?
string content = null;
var iframe = webBrowser.Document.GetElementsByTagName("iframe").FirstOrDefault() as Gecko.DOM.GeckoIFrameElement;
if(iframe != null)
{
var html = iframe.ContentDocument.DocumentElement as GeckoHtmlElement;
if (html != null)
content = html.OuterHtml;
}
I'm just posting this for anyone else that might get this problem
foreach (GeckoIFrameElement _E in geckoWebBrowser1.Document.GetElementsByTagName("iframe"))
{
if (_E.GetAttribute("class") == "testClass")
{
var innerHTML = _E.ContentDocument;
foreach (GeckoHtmlElement _A in innerHTML.GetElementsByTagName("input"))
{
_A.SetAttribute("value", "Test");
}
}
}
I got a similar problem so i did this
checkDoc.Window.Frames(1)
instead of
checkDoc.GetElementsByTagName("iframe")
value within the parenthesis (i.e. 1 here) depends of your index
I got this code
PublishingPage newPage = pWeb.GetPublishingPages().Add(fileName, layout);
newPage.Title = title;
However if the page exists it throws an exception and I want to check easily if it exists before
You could try this :
SPWeb web = properties.Feature.Parent as SPWeb;
PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(web);
foreach (PublishingPage page in pWeb.GetPublishingPages())
{
if (page.Name.Equals("myPage.aspx"))
{
// Do your stuff here
}
}
Or if you find it's not fast enough you could try this:
pWeb.GetPublishingPages().ToList().Find(x => x.Name.Equals(filename))