code.jpg

Atlanta Office DevCamp

Build Productivity Apps

Learn how to build apps using standard web technologies that extend the familiar Office and Office 365 experience and potentially sell them to over 1 billion Office users in 147 international markets.

At this DevCamp, you will learn the concepts of the new Office 365 API model and go deep into building out an end-to-end example on the Office 365 environment. Microsoft Office 365 DevCamps are free and fun events for developers, by developers. You do not want to miss this unique event presented by Microsoft technical experts.

Gear up and get building!

This is a jam-packed 1-day training course where you will get deep into the code after we gear you up with the tools and environment. Here is a 6 session topics:

1 – Intro to day (40 mins)

2 – Standing up the environment (40 mins)
Hands on lab (40 mins)

3 – Hooking into Apps for SharePoint (40 mins)
Hands on lab (40mins)

4 – Hook into Office 365 APIs via Standalone web application (40 mins)
Hands on lab (40 mins)

5 – Hooking into Apps for Office (40 mins)
Hands on lab (40 mins)

6 – Building native Android App (40 mins)
Hands on lab (40mins)

DevCamp Must-Haves

Note – this is a hands-on workshop.  To get the most out of your session, please don’t forget to bring your laptop.

In addition:

Fees

This free event is brought to you by your local Microsoft office. Delegates are responsible, however, for booking and funding their own travel and accommodation, as required.

read more
Danny RyanAtlanta Office DevCamp
code-flat.jpg

Join Us at Atlanta Office DevCamp on May 28th

Build Productivity Apps

Learn how to build apps using standard web technologies that extend the familiar Office and Office 365 experience and potentially sell them to over 1 billion Office users in 147 international markets.

At this DevCamp, you will learn the concepts of the new Office 365 API model and go deep into building out an end-to-end example on the Office 365 environment. Microsoft Office 365 DevCamps are free and fun events for developers, by developers. You do not want to miss this unique event presented by Microsoft technical experts.

Gear up and get building!

This is a jam-packed 1-day training course where you will get deep into the code after we gear you up with the tools and environment. Here are the 6 session topics:

1 – Intro to day (40 mins)

2 – Standing up the environment (40 mins)
Hands on lab (40 mins)

3 – Hooking into Apps for SharePoint (40 mins)
Hands on lab (40mins)

4 – Hook into Office 365 APIs via Standalone web application (40 mins)
Hands on lab (40 mins)

5 – Hooking into Apps for Office (40 mins)
Hands on lab (40 mins)

6 – Building native Android Apps (40 mins)
Hands on lab (40mins)

DevCamp Must-Haves

Note – this is a hands-on workshop.  To get the most out of your session, please don’t forget to bring your laptop.

In addition:

Fees

This free event is brought to you by your local Microsoft office. Delegates are responsible, however, for booking and funding their own travel and accommodation, as required.

read more
Danny RyanJoin Us at Atlanta Office DevCamp on May 28th
fork-sink.jpg

Syncing a Forked Version of the Office Dev PnP Repository

Recently, while trying to review all the new crunchy goodness from the Office Dev PnP GitHub repository, I noticed that my forked repository was not getting updated. As a relative git and GitHub n00b, I had to figure this out and thought I would share my solution (really, it is because I am getting old and this is an easy place to find things). Turns out, if you are an old TFS hound, this is not an intuitive process, but makes sense once you get through the steps. Here’s what I had to do to get my forked version of the Office Dev PnP repository up to date:

Open the shell for GitHub, or your terminal, and navigate to your forked version of PnP. Checkout your local master branch.

git checkout master

Check the current remotes by typing.

git remote -v

You should have at least the origin for your fork (if you cloned from your fork). Now set up an upstream remote.

git remote add upstream https://github.com/OfficeDev/PnP.git

Check that you have the new remote added.

git remote -v

upstream

Now, fetch the upstream changes

git fetch upstream

Finally, merge the changes into your master

git merge upstream/master

You now have all of the changes to the master local to your repository. Now, you must merge them into your remote origin/master

git push

This got my fork of the PnP repository up to date with the PnP teams April release.

sync

See the GitHub help for their examples for configuring a remote for a fork and synching a forked repository.

If you want to participate in the PnP community, be sure to follow their setup instructions found here so you can send pull requests.

If you know of a different or better way to do this, let this old dog learn some new tricks by leaving a comment below.

-HTH

read more
Pete SkellySyncing a Forked Version of the Office Dev PnP Repository
arrows.jpg

5 Critical Mistakes You Don’t Want to Make When Migrating to SharePoint 2013

 

Danny:             Hi this is Danny Ryan, VP of Business Development for ThreeWill. I’m here with Chris Edwards, Chris is a Senior Software Engineer for ThreeWill. Thanks for coming and doing this Chris.

Chris:               Thanks, glad to be here.

Danny:             Chris has helped out with a lot of our migrations and recently wrote a blog post on the 5 critical mistakes that you don’t want to make when you’re migrating to SharePoint 2013. I wanted to take a little bit of time out of his busy day and just sort of go through that blog post and cover those 5 things. Tell me a little bit more about things you’ve been doing recently, sort of things that have led up to writing this blog post?

Chris:               Sure, so more recently I’ve been doing a lot of things, really with a lot of our internal stuff, taking things from SharePoint and our own internal SharePoint extranet and pushing them out to Office 365. Kind of learning a lot of lessons about how to actually do that properly, or maybe not so properly, but learning the lessons in dealing with the fallout from that. Also been doing some work, both internal and external, with moving Jive customers to Office 365 and to SharePoint in general. Learning quite a few things about how to make that work, and trying to do a good job with that.

Danny:             Awesome, very cool. You had gone through and sort of looked at 5 mistakes that people have made. The first one that you point out, is a lack of knowledge of the product and platform or changes that have to do with that. Tell me a little bit more about that.

Chris:               That’s one of the things that if you’re not aware of like SharePoint 2013 there’s some things that’s quite a substantial difference from its previous version. Things like, the data sheet view, people that are used to working with SharePoint is used to a more Excel like experience working with lists and things like that. They may expect that data sheet view to just be the exact same in 2013, well it’s not quite the same thing, it’s a little different. They’ve made it better in the sense that it supports more browsers, but the whole copy/paste concept of working with Excel and dealing with it like it was previously, it’s not quite the same experience and it kind of throws people off a bit. Other things like the, more like an app centric model, things are more app storish type of feel to it in SharePoint 2013. Even custom lists are now apps, so people weren’t necessarily familiar with that, it’s a little different paradigm.

Then another big one is search is vastly improved, I would say in the new version of SharePoint. Its configuration is quite a bit different, so there’s a learning curve to go through and understand how to deal with that configuration. The reason why I put that in this post, is that you really need to spend time to understand that first before you just attempt to try and migrate to SharePoint 2013. Without just understanding it, you could migrate, and then be in a situation where you don’t understand how to configure it properly and confuse your users. That’s really, it’s just making people aware that they need to invest some time into understanding the differences, and what they’re really accomplishing [inaudible 00:03:21] 2013.

Danny:             That’s great. I also saw that you put a more detailed list in the post as well if people wanted to go find some more details including the ones that you’d covered. Now the next one that you have is incorrect hosting choice, tell me more about that one?

Chris:               The thought on the incorrect hosting choice is it’s really the bigger question of should I be in the premises or should I be in the cloud? Should I go ahead and move to Office 365. I think there seems to be some misunderstanding in terms of when go to Office 365, what do I give up? Am I giving up security? Am I giving up the ability to control things? Yes and no, but I think with the hesitation of some of those questions, and thinking through those questions I’ve seen people make the choice to go to an on premises solution. What they really need to be considering, some of the really nice features that Microsoft is throwing out with Office 365 and some of the cool new stuff that they’re continuing to enhance the product with, in that particular world.

I would encourage folks to check out more of what Office 365 has to offer and don’t just get bogged down into, do I have control or not? Yes, you do have control. Do you have as much control as you used to? No. There’s actually some more detail on that type of conversation in the new business operating system white paper that we put out there. You guys can take a look at that if you want to find more detail on that kind of conversation.

Danny:             I guess this is also were the hybrid comes in to play to were you may have a little bit of each?

Chris:               Exactly, and I bring this into play just because you really want to think through making a wise choice on where to host. Don’t just assume, I had on premises before I need to go ahead and do the same thing again. It’s really a good time to make a proper choice.

Danny:             I know for some other clients that we’ve actually guided them through that whole process of deciding in there. There’s even decisions if your deciding to go all cloud, that you need to make, so it’s not as straight forward sometimes as you might expect it to be. Now the next one that you have is not properly identifying customizations. What’s that all about?

Chris:               That’s more of the physical aspect of if I want to upgrade from say SharePoint 2010 or SharePoint 2007 to 2013. You just want to get things moved up the upgrade path. It’s very easy to overlook or just kind of leave things, maybe old stale content, things like that, in place. I’ve seen this happen were you know you may have some old connector type, some old web parts or old things lingering around that make their way into SharePoint 2013 and then it’s stuff that’s there in the list that’s just confusing to people. It’s just lingering things that you can potentially get away with, but it ends up becoming a part of your systems record basically, in 2013 and cause problems. Typically when you’re dealing with those, SharePoint 2013 does a good job of blocking you and not letting you upgrade but things do get through and you can confuse people if you don’t try to plan for and account for those customizations properly.

Danny:             Is there a way you can go see what customizations have been made?

Chris:               There’s actually, the blog post itself talks about a PowerShell command, it’s called Test SB Content Database, it does basic testing that say okay here is some customizations that are in place that I don’t amount aware of, I can’t find, I can’t resolve basically. I’ve got a web part, I can’t resolve where is lives in you system, I’m going to report that to you. There’s an example of how you’d go after that, maybe a feature has been installed in the old version of SharePoint and you try to bring it over into the new one. It doesn’t know how to find that. That particular PowerShell command is referenced in the blog post as well, will show you that kind of stuff.

Danny:             Now the next has to do with where your users are managed and not establishing an authoritative identity store. Tell me more about that.

Chris:               This is more of that, kind of that hybrid question as well, do you want your users to be only on premises only on your own company domain actor directory, maybe that’s what you want. Or do you want them to live in the cloud, maybe an Azure AD or do you want a combination of the two? It’s kind of, it’s very similar to what we talked about earlier with choosing the right hosting provider, choosing the hosting. It’s just making sure you understand kind of where the users live. I know we made a mistake, where we tried to, we set up our users independently, and then we tried to set up email after doing that and then we ended up finding we needed to go back and redo that operation. You want to avoid those kind of redos, if you will, of setting of users, you know making the mistake of trying to migrate, and these users are trying to come over again a second time. Therefore it’s creating duplicates. There’s little mechanical things that confuse people and just slow down the whole process.

Danny:             I like that we did this when we were moving over and not for someone else. Very cool. Now the last one that you have in here is a lack of communication preparation. What have you seen there?

Chris:               This is kind of a general, kind of a catch all. If you’re moving a company or corporate SharePoint or some sort of system of record into SharePoint 2013, I mean you really want to let the people know what’s going on. Give them a chance to back up their content or to be aware that there content is going to be moving. I’ve seen situations where there’s a deadline people have to, the IT shop has to get things moved over and they don’t necessarily communicate as best possible. Even if they do the best job possible of moving this content, making it work, if people aren’t comfortable with where it’s going and aren’t familiar with it, it could cause a project to fail. It’s just making sure everyone is on board. You’re dealing with a lot of peoples content, a lot of peoples stuff so it’s just making sure that the trust level stays.

Danny:             Great, well I appreciate you taking the time to do this. Just a reminder to all our listeners we actually have a webinar that’s coming up on April 17, that Chris and I will be having similar conversation to this and love for you to join us there. You can register for that by going to ThreeWill.com/calendar. Thanks so much again, Chris, for your time.

Chris:               Thanks.

Danny:             Ba-bye.

read more
Chris Edwards5 Critical Mistakes You Don’t Want to Make When Migrating to SharePoint 2013
stones.jpg

Top 5 Ways That Your Application Can Be Built on SharePoint in Office 365

 

Danny:             Hi, this is Danny Ryan, VP of Business Development for ThreeWill and I’m here with Eric Bowden. Eric is the Principal Consultant for ThreeWill. Thanks for joining me Eric.

Eric:                 Thanks Danny, thanks for having me.

Danny:             And today, what we wanted to do was cover a recent post that Eric had written on the top 5 ways that your application can be built on SharePoint in Office 365. Eric, first question, really is why write this? What were you thinking when you were putting this blog post together?

Eric:                 Foremost, Office 365 it’s a great platform for developing applications and I just want to be sure that folks who are using and making are getting a great benefit out of SharePoint and Office 365 today but I just want to be sure that folks are aware that there are incrementally easy ways to develop custom applications on the platform and get greater value out of it.

Danny:             Mm-hmm (affirmative).

Eric:                 I think a lot of times people are thinking, OK I have a custom need I want to develop a custom application on the platform and they’re thinking the most extreme the most complicated case in developing in SharePoint when in fact, there are really at least four levels of application development on the platform before you get into that mode that people normally think of as developing applications on the platforms. So I really wanted people to be aware of just how easy it is to really configure and customize the platform to get greater value out of it.

Danny:             I can see how like right now people are moving to the cloud that customization might be a dirty word, right? Because some of the things that might be prohibiting them from moving all the way into the cloud, so what you’re trying to say is with this, is basically don’t think that when we talk about building apps on Office 365 that you’re necessary talking about things like full trust code, you’re building out a custom app that what we’ve thought about in the past, things have actually changed with Office 365.

Eric:                 Yeah, that’s a great point. I think you’ve highlighted a key concern, you know people do have fears so they think of this as a multi-tenant environment.

Danny:             Mm-hmm (affirmative).

Eric:                 My organization is new to Office 365 and folks have a natural concern about anything that which they think of custom applications developed in the cloud and in this new kind of cloud environment. But, in fact, as we go through these options you’ll see that there are options which are really isolated only to one particular site and only one particular location within the cloud. So I just want to alleviate concerns that when I’m customizing the environment that it could have a broader impact.

Danny:             Got you. Now the first one you start out with is this SharePoint out of the box configuration. Tell me a little more about that one.

Eric:                 So this one, there’s a huge amount of power and capability in SharePoint merely from creating and configuring lists.

Danny:             Mm-hmm (affirmative).

Eric:                 So really this SharePoint out of the box configuration, this is lists and libraries, Office 365 has great support for office document types as well as video document types. So one of the popular options that we had have been with configuring video portals that allow users to easily find and view videos in Office 365. So there’s a lot of options which is really just configuring list libraries oh and custom views.

Danny:             Mm-hmm (affirmative).

Eric:                 So you can have views that help you easily find records, documents, and videos, grouping and sorting, and that’s really just configuration but there’s a great value that people can see just with that.

Danny:             Awesome.

Eric:                 And now the next one that you have is Work Flow Applications. Are these getting more complex as we work our way down? What’s happening as we look …

Danny:             Yep, yep exactly.

Eric:                 Yeah, so these are incrementally getting more and more complex as we go but really not a lot more complex as a builder. They’re really a gradual step and so the next one is Work Flow applications, so what I’m referring to hear is our SharePoint designer work flows. And there are out of the box work flows that are provided. For example, approval work flows. We were working recently on a project that made use of document sets and an approval work flow for that document set. This document set was around purchase orders and then the invoices that are charged against those purchase orders and so there is an approval process for invoices and a purchase order, and that was just an out of the box approval work flow.

Danny:             Nice, nice. Now the next one that you have is Site Pages and Java Script applications. Tell me about that.

Eric:                 Yep, so this one is a pretty big jump in the functionality that you get but it’s not a real big jump in terms of the complexity the developer complexity. So we are getting into the Java Script, we are getting into custom pages, but these Java Script files and the custom pages are really being uploaded or we might use the word injected, so they’re kind of being injected into this particular site. And it’s only scope of that application is only a specific site and these are cases where we might have custom forms or custom pages to support a business process, but still in terms of the developer complexity and the impact to the Office 365 environment is still, it’s very low. The same as the first two options.

Danny:             Got you. The next on is Windows Desktop and Click Once application.

Eric:                 Right, so this is … Up until this point we’ve really been looking at either simply configuring SharePoint or what we would refer to as browser customizations, but now with the Windows Desktop and Click Once applications, these are options where we have some more heavy custom application development that needs to occur. For example, one project that we worked on, used a click once application to generate PDF documents. And so back in the old days this would have been server site code running on a SharePoint server but with Windows Desktop applications and Click Once apps we can take that heavy code centric processing and move it off onto a desktop application or as a click once app.

Danny:             Nice, Nice. Now the final one that we have here is SharePoint apps.

Eric:                 Yeah, so SharePoint apps all the way to the end of the 5 that I’ve listed, what I see as the most complex but it’s also the richest in terms of the features that you can build into it. SharePoint apps, these are what most people think of. When folks are out in the field, saying I need to create some custom applications, SharePoint apps is what people are most thinking of and I really … Part of this blog is a way to discourage that because SharePoint apps, that’s where we’re looking for usually an Azure environment. These are called provider hosted apps, where the heavy processing and the UI is hosted outside of SharePoint. These have the highest functionality …

Danny:             Mm-hmm (affirmative).

Eric:                 But they also have the infrastructure that you need to have set up and they’re the most complex of the five and they’re really the kind of app, of course, we would like to see more of but it’s really here impart to illustrate that there is a lot that can be done before you get to SharePoint apps.

Danny:             Nice, Nice. I appreciate you taking the time to spell these different options out. One last question, it seems like if you have all these different options, how do you decide which one you go with? Is there a, I don’t if there’s a thought that you’d want to start with the simpler modes first and then decide if it has to have some functionality that requires a SharePoint app then you go with that or is there any rules of thumb that you’ve run by that determines what you end up getting?

Eric:                 Right, I would say … I always favor this in my application design is just shoot for the simplest approach that will meet the need. However, you don’t want to be too short sided. So be thinking about, what is this application going to look like in the next two or three releases.

Danny:             Mm-hmm (affirmative).

Eric:                 Also, be thinking about what will it take to sort of translate if I take a simpler approach that I don’t think is going to meet my needs down the road, be thinking about what it’s going to take to translate that sort of simple approach into a more complicated design down the road. For example, maybe I might start with site pages in Java script applications, which is sort of my third tier out of five.

Danny:             Mm-hmm (affirmative).

Eric:                 And then maybe down the road, I might want a full blown SharePoint app because I have some back end processing that’s necessary. Think about what kind of job that is.

Danny:             Mm-hmm (affirmative).

Eric:                 You know off the cuff, it’s usually not that big of a job because you’re just kind of moving those things from SharePoint into a provider hosted environment.

Danny:             I appreciate you taking the time to lay out these options for us and for any of the listeners if you’re interested in building out apps on Office 365, please feel free to drop by our website ThreeWill.com and look for this blog post, “Top Five Ways Your Application can be Built on SharePoint and Office 365.” Drop by, leave a comment for Eric if you’ve got other things that you want to add to the conversation and we really appreciate it. Thank you, Eric, for your time.

Eric:                 You bet.

Danny:             And we appreciate you listening to this podcast.

read more
Eric BowdenTop 5 Ways That Your Application Can Be Built on SharePoint in Office 365
top-five-list.jpg

Top 5 Ways That Your Application Can Be Built on SharePoint in Office 365

Your Application Can Be Built on SharePoint in Office 365

Many SharePoint users who have moved their infrastructure to Office 365 are not aware of just how easy it is to amplify the benefit of SharePoint in Office 365 through the development of custom applications.  Custom applications can be a great multiplier for Office 365 because they uniquely tune the powerful feature set provided by the platform to your business.

There are a number of options available to create applications in Office 365.  The list below includes 5.  Many of these options are low complexity and require only site owner permissions.  Further in the list, the options become much more powerful and require additional permissions in SharePoint.

  1. ​SharePoint ‘Out of the Box’ Configuration

    • ​Example: ​Intranet site to allow users to easily find and watch training videos.
    • How to get started: You just need a SharePoint site and Site Owner permissions.
  2. Workflow Applications

    • ​Example: Multi-user process for creating and approving purchase orders and invoices.
    • How to get started: You need a SharePoint site, and you will need Site Owner permissions.
  3. Site Pages and Javascript Applications

    • ​Example: A site which presents training materials as videos or PowerPoint, with an associated quiz to facilitate learning.
    • How to get started: You need a SharePoint site and Site Owner permissions
      • Notice a pattern?  The first three techniques for developing custom applications are available for almost everyone.  These options are very powerful and can meet the needs of many complex business applications.
  4. Windows Desktop and Click-Once Applications

    • ​Example: Custom application which creates price cards for cellular phones, in PDF format, utilizing list data stored and approved in SharePoint.
    • How to get started: You will need a SharePoint site and site owner permissions.  Users who will use the click-once application will need to have privileges to install new applications on their desktop.
  5. SharePoint “Apps”

    • ​Example: Employee hiring and onboarding application for a major league sports team.
    • How to get started: You will need a SharePoint site, and you will need site collection administrator privileges.  You will also need an account in Microsoft Azure.  However, don’t get concerned about the need for Azure.  Azure is becoming more and more common across companies of all sizes, and it’s easy to get started if your company is not already using Azure.

Have you built on SharePoint or you are unsure if the application can be built in your Office 365 environment?  Contact us or comment below.


SharePoint is a web application platform in the Microsoft Office server suite. Launched in 2001, SharePoint combines various functions which are traditionally separate applications: intranet, extranet, content management, document management, personal cloud, enterprise social networking, enterprise search, business intelligence, workflow management, web content management, and an enterprise application store. SharePoint servers have traditionally been deployed for internal use in mid-size businesses and large departments alongside Microsoft Exchange, Skype for Business, and Office Web Apps; but Microsoft’s ‘Office 365’ software as a service offering (which includes a version of SharePoint) has led to increased usage of SharePoint in smaller organizations.

While Office 365 provides SharePoint as a service, installing SharePoint on premises typically requires multiple virtual machines, at least two separate physical servers, and is a somewhat significant installation and configuration effort. The software is based on an n-tier service oriented architecture. Enterprise application software (for example, email servers, ERP, BI and CRM products) often either requires or integrates with elements of SharePoint. As an application platform, SharePoint provides central management, governance, and security controls. The SharePoint platform manages Internet Information Services (IIS) via form-based management tooling.

Since the release of SharePoint 2013, Microsoft’s primary channel for distribution of SharePoint has been Office 365, where the product is continuously being upgraded. New versions are released every few years, and represent a supported snapshot of the cloud software. Microsoft currently has three tiers of pricing for SharePoint 2013, including a free version (whose future is currently uncertain). SharePoint 2013 is also resold through a cloud model by many third-party vendors. The next on-premises release is SharePoint 2016, expected to have increased hybrid cloud integration.

Office 365 is the brand name used by Microsoft for a group of software plus services subscriptions that provides productivity software and related services to its subscribers. For consumers, the service allows the use of Microsoft Office apps on Windows and OS X, provides storage space on Microsoft’s cloud storage service OneDrive, and grants 60 Skype minutes per month. For business and enterprise users, Office 365 offers plans including e-mail and social networking services through hosted versions of Exchange Server, Skype for Business Server, SharePoint and Office Online, integration with Yammer, as well as access to the Office software.

After a beta test that began in October 2010, Office 365 was launched on June 28, 2011, as a successor to Microsoft Business Productivity Online Suite (MSBPOS), originally aimed at corporate users. With the release of Microsoft Office 2013, Office 365 was expanded to include new plans aimed at different types of businesses, along with new plans aimed at general consumers wanting to use the Office desktop software on a subscription basis—with an emphasis on the rolling release model.

read more
Eric BowdenTop 5 Ways That Your Application Can Be Built on SharePoint in Office 365
happy-trees.gif

SharePoint Document Generation – Part Deux

SharePoint Document Generation Introduction

I promise I won’t get off on a rant this time. Actually, I have decided to pattern my life after Bob Ross and be perpetually calm. The previous post described how the overall pattern we were establishing should enable flexible document generation. The interfaces and API were simplified to enable use from a variety of sources. Specifically, for most (not all) of our clients the source is SharePoint. But the basic document building blocks could be used from a console application, SharePoint, PowerShell or other environments. There are really three basic steps involved to build a document now using this pattern.

  • Creating a View (Document Template)
  • Loading the View from a Document Library
  • Building our Model from SharePoint Content
  • Generating and saving to a Document Library

Creating a View (Document Template)

To enable the view portion of our pattern, we need to create a template that serves as our view. In this case the view is a Word document that will serve as a template for our end documents. Using Content Controls we can mark up the document to include references to single elements, or build complex tables using Content Controls. Rather than rehash the process of adding Content Controls to Word documents, Erika Ehrli has a great starter article. As always, check out Eric White’s blog for other examples and information regarding Content Controls and Open Xml.

In the end, our Word document will contain Content Controls that enable mapping data to a content control(s), or that map rows and columns of data to a table or other structure for the Word document. Once we have this, we need to store this template in a known location. For most of our clients, we deploy these templates as documents to Document Libraries in SharePoint as part of a Feature or overall Solution Package.

Loading the View from a Document Library

Once we have a template marked up with the static content and the content placeholders, we can load this view into an IDocumentTemplate instance. From a UI perspective, we’ve had client’s ask to create documents from CustomActions on a SharePoint list items’ ECB menu, from a button on a web part that accepts other input data, and even from event handlers. The entry point may vary, but the next step is always the same. The code below shows how we obtain the template and turn this into an implementation of IDocumentTemplate.
SPDocumentLibrary templateDocumentLib = web.Lists["Templates"] as SPDocumentLibrary;
//build final path for the document, root folder, sub folder, etc.
//... (code elided)
string templatePath = site.RootWeb.Url + templateDocumentItem;
IDocumentTemplate documentTemplate =
new SharePointDocumentTemplate(SPContext.Current.Site.ID,
web.ID, new Uri(templatePath ),
site.RootWeb.GetFile(templatePath ).OpenBinary());

In this case, SharePointDocumentTemplate implements IDocumentTemplate. The call to GetFile(…).OpenBinary() returns a byte[] and enables access to the IDocumentTemplate.ToArray() method. We’ll use this byte[] to create a MemoryStream and process the template as a view. We now have our IDocumentTemplate to use in our call to WrodDocumentBuilder.BuildDocument(IDocumentTemplate documentTemplate, IDocumentModel documentModel) of our controller. Next, we need to build our model.

Building our Model from SharePoint Content

We have our view (IDocumenTemplate), and now we want to get that data that will populate the template. The following code contains the IModelBuilder interface definition and the call to an implementation of the interface to build a model.
public interface IModelBuilder
{
IDocumentModel GetDocumentModel();
}
//... (code elided)

 

//build the model for the document
IModelBuilder documentModelBuilder =
new StatusReportModelBuilder(SPContext.Current.Web,startDate,endDate,
includeChildWebs);
IDocumentModel documentModel = documentModelBuilder.GetDocumentModel();

What is most interesting about this call is how simple and powerful it is. Behind the scenes we use LOTS of LINQ and some Func<> delegates to make a very simple, flexible and extensible pattern to query data.

Review our description of IContentMapping and IContentMappingCollection from my previous rant. The content mappings are a source agnostic interface definition that lets us query variable sources, but they require transformation into the various IContentMapping implementations. The IQuery interface defines the way do this from any source, including SharePoint. IQuery, and the BaseQuery base class, enable us to set up base SharePoint List query functionality, which is then extended for specific scenarios like recursive Site queries, queries using SPSiteDataQuery, or just basic CAML queries, to return our content mappings in a model form we can use.
public interface IQuery

{
List
> Query();
IEnumerable QueryReturnListItems();
}

public abstract class BaseQuery : IQuery
{
public SPList ListToQuery { get; set; }

public Func Predicate { get; protected set; }
public string[] FieldNames { get; protected set; }

public BaseQuery(SPList listToQuery, string[] fieldNames)
{
ListToQuery = listToQuery;
FieldNames = fieldNames;
}

public abstract List
> Query();

 

//... (elided code)
}

In the end, our call to documentModelBuilder.GetDocumentModel(); returns us a fully fledged IDocumentModel.ContentMappings collection of data for all of our content in the template. This data may have come from any container in a site collection – single lists, aggregated lists or content types across lists and sites, etc. Neat, clean, and powerful!

Generating and saving to a Document Library

Great, we have our view, and our model, now let’s generate a document. Simply call the BuildDocument() method with our documentTemplate and documentModel and let the magic happen.
//Generate the document and get the byte[] back
byte[] newDoc = documentBuilder.BuildDocument(documentTemplate, documentModel);

 

//save the byte array to the folder
web.Files.Add(newDocPath, newDoc, web.CurrentUser,
web.CurrentUser, DateTime.Now, DateTime.Now);

Again, the previous post explains how the call to BuildDocument walks over the template and model and maps the content in the model to the content placeholders in the view. Finally, we take the byte[] of the new document and save this file to the web and path for the correct document library.

Conclusion

I would love to take credit for this, but much of the credit goes to Sean Hester for implementing an elegant and extensible document generation pattern that can be consumed from SharePoint and many other sources. Thanks Sean! Also, whenever I mention Open Xml, I always think of and thank Eric White for providing an incredible array of useful and informative SharePoint, LINQ and Open Xml blog posts.

Photo Credit – Bob Ross by Dave Nicoll, on Flickr

read more
Pete SkellySharePoint Document Generation – Part Deux
rant1.jpg

Document Generation Rant

The Problem

I don’t want to get off on a rant here, but can we solve this document generation problem once and for all? Ever since Gutenberg moved his first set of metal letters, business users have been asking for documents to be created faster and faster. Johannes probably thought he addressed all of the challenges, but even recently, if a business process required the generation of documents in a dynamic fashion, there were several challenges to overcome including:

  • Server side document generation
  • Template and data mapping
  • Configuration and flexibility

Now, Heraclitus might have said you can never step twice in the same river, but he certainly would understand every programmers desire to stay DRY. We want to solve these kinds of problems once, right? For those of us who use Microsoft technologies to address business problems, the first two challenges have been addressed in recent years by Open Xml and Word Content Controls. There are many excellent resources and samples of how to use these two advances to solve simple document generation concerns (see References and Credits below). However, several of our clients at ThreeWill over the last 2 years have asked for solutions that address the last challenge: integrate these two advances, and make the solution flexible through configuration.

Recognizing the Pattern

Every document generation solution has some set of data that needs to be applied to a template or templates on a repetitive basis. It’s not like we need Rorschach to help interpret this pattern, the data is our Model, the template is our View, and we need to create a Controller to manage the generation activity – even my broken proboscis smells the MVC pattern. To solve this problem once, we want the data to be able to come from a variety of places, including Office Client application like Excel, a database, web service, SharePoint, etc., and the templates (all Word files with Content Control placeholders in our present case) which should be able to come from local files, a file share, a SharePoint document library or a database. The only thing missing is a Controller implementation to merge the model and the view in a generic way.

The Model

To ensure our document generation framework can handle a wide variety of data, our model is based on several simple interfaces. The simplest way to get a consistent model that would support multiple document types was to use basic .NET types that mapped single values, and table or list based values. I hear you saying , “Nice job Einstein. Some surfer solves physic’s most difficult problem and poses a theory of everything, and the best you can come up with is a couple of interfaces?”. Yes, they are simple, but do we really need a Hadron collider to generate documents?

The simple interfaces enable us to build up from a simple mapping of a ContentControlName (based on the tag in the Content Control in the Word Document). The first interface, IIndividualContentMapping, identifies a simple mapping of one tag name to a value, and can then be used to replace all instances of ContentControls with that tag.
public interface IIndividualContentMapping : IContentMapping
{
string Value { get; }
}

The second interface, ITableContentMapping, defines a map of a List of tags (Mappings) as a template row for a table. This template row mapping is used to copy a prototype row and then use the List of rows (Value) to build a table.

public interface ITableContentMapping : IContentMapping
{
List> Value { get; }
List Mapping { get; }
}

The View

No, we are not talking about the show where host’s opinions are worth less than a collateralized debt obligation containing a pool of Florida, Arizona and Southern Californian mortgages. What we are talking about is the documents that will serve as our view in our pattern implementation. In this case, the templatized Word documents that contain ContentControls. These content controls are mapped (by convention) to the ContentControlNames in the Model’s IContentMapping interface. The two interfaces mentioned before, IIndividualContentMapping and ITableContentMapping, enable mapping our model into our view for simple mappings and complex mappings for tables or lists.
public interface IDocumentTemplate
{
Uri FileUri { get; }
Byte[] ToArray();
string GetTemporaryFileName();
}

This interface definition allows us to rely on a consistent API of getting a byte[] that can be used to seed a memory stream for building documents using the OpenXml SDK.

The Controllers – IDocumentBuilder and IComplexDocumentBuilder

We decided that the best way to implement a flexible controller was to define one or more interfaces that would let us leverage Open Xml file types (i.e. not just Word files) to consistently apply the pattern. Here’s what we came up with.
public interface IDocumentBuilder
{
Byte[] BuildDocument(IDocumentTemplate documentTemplate,
IDocumentModel documentModel);
}
public interface IComplexDocumentBuilder
{
byte[] BuildDocument(List documentTemplates, List documentModels);
}

Now, we’re not trying to argue whether these interfaces are the Platonic Ideal, but no one can argue their truthiness. Splitting these interfaces let’s us build simple documents, as well as complex documents composed of multiple templates (views) and multiple data sets (models).

Generating a simple document is accomplished with the following code.
public byte[] BuildDocument(IDocumentTemplate documentTemplate,
IDocumentModel documentModel)
{
...//some code ommitted
byte[] generatedDocBytes = null;

try
{
//make a writeable copy of the template as the documentStream
using (MemoryStream docStream = new MemoryStream())
{
//write template bytes to doc stream
docStream.Write(documentTemplate.ToArray(), 0, documentTemplate.ToArray().Length);
//open the template doc for edit
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(docStream, true))
{
//- Use OpenXML SDK to update Content Controls
WordMLManager wordMgr = new WordMLManager();

foreach (string key in documentModel.ContentMappings.Keys)
{
IContentMapping mapping = documentModel.ContentMappings[key];
if (mapping is TableContentMapping)
{
ITableContentMapping tableContent = mapping as ITableContentMapping;
//map table content
wordMgr.UpdateContentControlsInTable(wordDoc.MainDocumentPart, tableContent);

}

if (mapping is IndividualContentMapping)
{
//map individual content controls
IIndividualContentMapping contentTagMapping =
mapping as IIndividualContentMapping;
//wordMgr.UpdateOpenXmlPartContentControlsByTagName(wordDoc.MainDocumentPart,
// _individualTags, individualValues);
wordMgr.UpdateContentControlsByTagName(wordDoc.MainDocumentPart,
contentTagMapping.ContentControlName, contentTagMapping.Value);
}

}
}
generatedDocBytes = docStream.ToArray();
}
}
...//some code ommitted
return generatedDocBytes; ;
}

The real magic, not the monotone, David Blaine, “I’m sitting in a box” magic, happens thanks to the PowerTools for OpenXml, which allows you to compose a document from multiple templates and data sources. The code snippet simply uses the IDocumentBuilder implementation to build a series of documents, and then “stitches” them together to form a larger, composite document. Magic!
... //code removed
for (int i = 0; i < documentTemplates.Count; i++)
{
IDocumentBuilder documentBuilder = new WordDocumentBuilder();
byte[] componentDocument = documentBuilder.BuildDocument(documentTemplates[i],
documentModels[i]);

//add the componentDocument to the sources to be "stitched" together later
sources.Add(new Source(WordprocessingDocument.Open(new
MemoryStream(componentDocument), false), true));
}
// now create a "stitched together" document from all of the source documents.
using (WordprocessingDocument compiledDocument =
DocumentBuilder.BuildOpenDocument(sources, documentStream))
{
compiledDocument.FlushParts();
//close the source document references
foreach (Source source in sources)
{
source.Close();
}
}
aggregateDocument = documentStream.ToArray();
...//some code omitted
return aggregateDocument;
}

Conclusion

This pattern, which we’ve refined on several projects over the past two years, has worked very well for us. Since the the pattern is based on simple interfaces that build up collections of data, it is very flexible. After all, this was about defining the framework once. It is simple enough to extend this to PowerPoint or Excel, and although neither offers a clean “ContentControl” to replace, there are ways to do this. So maybe this solution isn’t as flexible as the love child of Stretch Armstrong and Mary Lou Retton, but it certainly does get the job done.

Of course, that’s just my opinion, I could be wrong. Leave a comment below and feel free to agree or start your own rant.

Part 2 will cover the application of this pattern inside of a SharePoint application.

References and Credits

Thanks to Sean Hester who contributed significantly to the successful implementation of this pattern for our clients. A huge thanks goes out to Eric White for providing guidance and samples for much of the underlying code for these solutions. And for those looking to build on a solid Open Xml foundation, you will find some incredible examples in the PowerTools for Open XML.

read more
Pete SkellyDocument Generation Rant
downloading.jpg

Turner DevConnections Event

Here is a link to the presentation – Turner 2007 Keynote (pdf, 8MB)

This focused on an example of an Office Business Application:

  • Part 1 – Office 2007 Integration with line of business data/information
  • Part 2 – Workflow Foundation for centralized process management / SharePoint 2007 for consolidated views/dash boarding
  • Part 3 – Windows Presentation Foundation/ Virtual Earth for immersive experience and visualizing large data sets for better decision making

Thanks to Kirk Evans from Microsoft and Don Browning of Turner for including us and putting on a great event.

read more
Danny RyanTurner DevConnections Event
tools1.jpg

Visual Studio Tools for Office

As part of the recent ThreeWill “Next Level” seminar at Microsoft in Alpharetta, Eric Bowden and I showed a Word 2007 Visual Studio Tools for Office Second Edition (VSTO SE) Add-in that used WSS 3.0 Web Services to generate a basic status report. The Add-in uses WSS 3.0 Web Services to pull data from a custom list and a task list. Once the data is retrieved from SharePoint lists, a custom UserControl contained in the Office Task Pane can update Word 2007 Content Controls and create a task table in the Word document in response to user events. Finally, a custom Ribbon tab enables performing the same actions from the Ribbon as from the Custom Task Pane.

Several people asked for the code, so here is the code and some highlights. All of the code is available here.

First, you’ll need Word 2007, Visual Studio 2005 and VSTO SE. To install VSTO SE, visit the Office Developer Center and download. Rather than rehash a how-to on creating a VSTO SE Add-in, check out the articles, code samples, and how-to’s on the VSTO SE site. A basic Add-in, with a custom Task Pane and Ribbon similar to the “Next Level” demo, can be created by following the steps in the samples and how-to’s found there.

Once I had a basic Add-in completed, I created a Word document template (Weekly Project Status Report.docm) for the status report, added the Content Controls to the template and added the template to the Add-in project. To add Content Controls to a Word 2007 document you must use the Developer tab which is disabled by default. If this tab is not visible, click the Office Button, then “Word Options”, and check “Show Developer tab in the Ribbon” to enable the Developer tab.

After the Status Report template was added to the project, I created 2 SharePoint lists. The first list, a custom list named Projects, should have the following column definitions as displayed in the Settings menu for the list.

The second list, a Task list named ProjectTasks, should have these column definitions as displayed in the Settings menu for the list.

Then I added a Web Service reference to the Lists.asmx web service, /_vti_bin/lists.asmx, of the site that contained the project lists. To retrieve the Project list data was a straight forward call to the lists.asmx Web Service. Once the XmlNode is returned, simply walk the child elements and add them to a List<Project> collection.

Lists lists = new Lists();
lists.PreAuthenticate = true;
lists.Credentials = CredentialCache.DefaultCredentials;
lists.Url = m_wssListServiceUrl;
XmlNode list = lists.GetListItems("Projects", null, null, null, null, null, null);
foreach (XmlNode node in list.ChildNodes[1].ChildNodes)
{
if ((node.Attributes != null) &amp;&amp; (node.Attributes["ows_Title"] != null))
{
string linkTitle = node.Attributes["ows_LinkTitle"].Value;
string projectName = node.Attributes["ows_Project_x0020_Name"].Value;
string extranetURL = node.Attributes["ows_Has_x0020_Extranet"].Value == "1"
? node.Attributes["ows_Project_x0020_URL"].Value
: "";
string teamLead = node.Attributes["ows_Team_x0020_Lead"].Value;
projects.Add(new Project(linkTitle, projectName, extranetURL, teamLead));
}
}

The List<Project> collection is filled and the combo box on the StatusReportControl is bound to this data. Changes to the combo box update the controls in the custom Task Pane and the Content Controls contained in the Word document by calling SelectContentControlsByTag. Each named Content Control then updates the Range with the specific project item data similar to the following code.

//update content controls in document
if (Globals.ThisAddIn.Application.ActiveDocument.ContentControls.Count &gt; 0)
{
object controlRef = 1; //control references start with 1 not 0
ContentControl projectNameControl =
Globals.ThisAddIn.Application.ActiveDocument.
SelectContentControlsByTag("ProjectName").get_Item
(ref controlRef);
projectNameControl.Range.Text =
((Project) comboBox1.SelectedItem).ProjectName.ToString();
//other calls omitted
}

Notice that the controlRef number is not zero based and must be referenced beginning with 1. Also, the call to get_Item() is required since there can be multiple controls with the same name and this ensures you are updating the correct control.

The status report also enables adding a table of tasks from the ProjectTasks list. This call to the lists.asmx web service involves building a Query node to provide to the lists web service. To build the Query node, the user can select a date range that tasks were completed within. Using the Query node, the lists web service retrieves the tasks and passes the returned XmlNode variable to a method to convert the node into a table in Word.

XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
string queryString =
"";
queryString +=
tasksCompletedAfter.ToString("s", CultureInfo.InvariantCulture) + "";
queryString += "";
queryString += tasksCompletedBefore.ToString("s", CultureInfo.InvariantCulture);
queryString += "";
ndQuery.InnerXml = queryString;

XmlNode ndListItems = listService.GetListItems(taskListGuid, null, ndQuery,
ndViewFields, null, ndQueryOptions, null);
taskTable = CreateActivitiesDataTable(ndListItems);

Finally, the Ribbon button definitions in NextLevelRibbon.xml have “onAction” attributes that call code similar to that listed above. The custom Ribbon buttons simply change the contents of the project name Content Control and add the tasks table based on the date interval selected.

There’s lots of room for improvement and enhancements to this Add-in sample, but hopefully this shows some of the power of combining SharePoint list data, or any other external data source, within a familiar environment like Word to enable users and data to work together better.

read more
Pete SkellyVisual Studio Tools for Office