Sunday, December 16, 2018

I’ll be back for the SharePoint Conference 2019 in Las Vegas!

We’re approaching holiday season and Oslo, Norway where I live, has gotten a nice coating of snow to brighten up those dark evenings. Christmas lights are also popping up, bringing that jolly feeling all around.

And what else has that jolly feeling all around you might ask? SharePoint Conference in Las Vegas Baby! Yes, it’s true, SharePoint Conference came back last year, and SharePoint Conference 2019 (SPC19) is arriving with a twist. I’m back! Last time I was in Vegas was for the SharePoint Conference 2014, which means come May 21-23, 2019, it will be a whopping 5 years since the last time. I’ve had nothing but great experiences with the SharePoint Conference in the past, and I’m sure this time will be no different.

Save $50 and register via https://pzl.no/SPC19 today!

SPC19 is one of two major Microsoft events where Microsoft product groups announce new and upcoming features for the Office 365 and SharePoint suite. The other conference is of course Microsoft Ignite being held in November in Orlando, Florida. Which means attending one or both of these conferences puts you right in the middle of where it happens.

Governance and Lifecycle management

Back in 2014 search in SharePoint was still hot and sunny, and that was my speaking topic. This time around I’m older and wiser and have devoted my time to governance and lifecycle management of Office 365 Groups and Teams in a presentation titled: “What Options do You Have to Govern the Lifecycle of Office 365 Groups and Teams?”

Why have I switched from talking about the wonders of search capabilities in Office 365, over to boring admin stuff? It’s not that far a leap as you might expect, and certainly not boring. Search is all about findability and weeding out the bad content in order to surface the good content. Which plays right into managing content in Office 365 Groups and Teams. You need to focus on what’s valuable, and rid yourself of the rest.

Office 365 Groups and Teams introduce many workloads such as document management, tasks management, and chat logs. Built into the Office 365 platform your organization has many tools and functions available to help control how information is governed and to help you control the lifecycle of the information stored within the groups and teams.

The goal of my presentation is to show what tools are available in the Office 365 suite to help with lifecycle management and to show how you can use them to ensure a healthy environment with reduced information bloat while still maintaining information control and integrity. Some of the functions are available in different administration UI’s, but for the IT Pro’s loving PowerShell out there, most of it today is available via PowerShell and the Microsoft Graph.

Using admin UI’s and PowerShell I will dig into some of those capabilities and show how you can get hold of the information you need in order to implement your business rules and requirements for lifecycle management of Office 365 Groups and Teams.

I will also touch on what end-user licenses are needed for being license compliant when using the different features available to you. And who knows, working in an evergreen platform, things might very well change between now and May, which lets me adapt this session as well as time closes in on May 21st.

There is more!

Even though you might find my session good enough reason to travel to SPC19, there is more.

Sunday and Monday before the conference has been reserved for full day workshops covering topics such as SharePoint Framework development, governance of Microsoft 365, security of Office 365 using Enterprise Mobility and Security settings, and how to get started with PowerApps and Flow.

Once you have filled your brain with hands-on training from the workshops, it’s time to dig into all of the 200+ sessions which are to be presented by an awesome speaker lineup with experts from Microsoft Engineering as well as well-renowned experts from all around the world – all passionate and eager to share their knowledge and experience with you. Also being present in Las Vegas gives you the possibility to talk to these experts about your problems, experiences and concerns in person.

With all the other attendees at SPC19, make sure you strike up a conversation during early morning breakfast, during energy re-filling lunches and during after-dinner drinks, and you will see that you can learn so much from fellow peers in the space of Microsoft 365 and Office 365. Even though your organization is unique, you’d be surprised to see how much it has in common with other organizations using the same platform. And if you didn’t know, the Office 365 and SharePoint community is one big sharing community. What it all boils down to is how to use the platform as smart as possible, and to get the job done in an efficient, smart and compliant manner.

Register and Save $50 on the ticket

If Las Vegas in May seems like your thing, register via https://pzl.no/SPC19 to use my discount code SVENSON (all caps) to save $50 on the ticket, which you instead could turn into millions in the casino. Register before January 15th, and you may also receive an XBOX One, Surface Go or other cool stuff depending on your package.

Register now, register early, see you there!

Sunday, December 9, 2018

Puzzlepart presents modern PDF conversion/export for SharePoint

screenshot

If you have Adobe Creative Cloud licenses you might have installed Adobe’s integration with SharePoint and OneDrive to allow PDF handling from document libraries. Two of the included functions from Adobe are to convert files to a PDF file in-place in the library, and to download files as PDF from the library.

See https://adobe.com/go/o365pdf for more information on Adobe’s offering.

If you however don’t have the required Adobe licenses or don’t want to go through their install process I’ve cooked up a simple solution – Just for you!

Today the API’s in SharePoint are at a point where you can create a SharePoint Framework solution using first class functionality in SharePoint to perform PDF conversion without any extra modules.

By installing our tenant wide list extension you can with very few clicks enable conversion and downloads of files as PDF files in all your SharePoint document libraries.

Get the solution at https://github.com/Puzzlepart/spfx-solutions/blob/master/Pzl.Ext.PDFExport/README.md

Enjoy!

Saturday, December 1, 2018

Presentation and files from my ESPC18 session on Groups/Teams governance

I had an awesome time presenting “What Options do You Have to Govern the Lifecycle of Office 365 Groups / Teams?” at the European SharePoint Conference this week. The audience seemed very interested and I got a few questions at the end for every one to hear, and 20 minutes 1 on 1 after that.

The demo scripts can be found at https://github.com/wobba/espc18

Wednesday, November 14, 2018

Sending e-mails in Microsoft Flow using SharePoint

Introduction

image

A lot of Flow scenarios involve sending alert or information e-mails to someone in your organization.These are typically e-mail which don’t require a response. Something happened, and you want to notify someone. And this is what this post is all about.

Yeah, yeah, we should cut down on e-mails, but that’s not happening any time soon – so read on!

Wednesday, October 31, 2018

How to remove yourself from an external tenant/organization–when you’re done collaborating and it clutters Teams

You might have clicked your organization name in Teams and see this long list of external tenants you might have been part of for some reason. When you’re done you might want to weed the list.

image

Leaving just the teams/channels will still show the external tenant, so in order to remove yourself navigate to: http://myapps.microsoft.com. This page also lists application you have access to in external tenants.

On this page click your photo and pick Profile.

image

The next page will list all tenants where you are a guest, and you can remove yourself as a guest user manually.

image

Note that this will remove you as a guest user in the external tenant. This means that if someone has shared documents or similar with you, you should not remove yourself as a guest user. But if you don’t have any relationship with the external tenant any more, you can safely remove yourself – and they can re-invite you if needed.

The official documentation for this can be found at https://docs.microsoft.com/en-us/azure/active-directory/b2b/leave-the-organization.

Monday, October 22, 2018

Get Hygge with it – Your 5 Step Guide to ESPC18

1. PLAN Your Sessions

Explore the ESPC18 SCHEDULE to identify what sessions you’d like to attend. Create your own schedule suited to you. If you are travelling with colleagues, divide and conquer by  attending different sessions. Afterwards swap notes to increase your learning.
Don’t have time to delve through our 120+ conference schedule? We have created dedicated pages to save you time. Check out the ESPC conference schedule based on IT PRO, DEV, BDM, AZURE or MICROSOFT SESSIONS.

2. CONNECT with Your Peers

Join the ESPC18 App (Login details announced in the coming weeks) & follow the hashtag #ESPC18 to find out whose attending. Why not make your presence known by sending out a tweet introducing yourself. Arrange to meet new individuals at ESPC – you never know what you might discover! Helpful tip: Carry some business cards with you to share with the new people you meet.

3. LEARN, Learn, Learn

Before arriving at ESPC, take some time to identify what questions you want answered. Prepare them advance to ask during a session Q&A. Why not take a break from sessions and advance your skills at the ESPC labs or check out the Ask the Experts session. Remember, it’s good practice to note three important key takeaways from each session.

4. Have Fun

With 2,000 delegates expected to attend, ESPC offers a host of exciting day and night experiences. Check out the WOMEN IN TECHNOLOGY LUNCH, a jam packed EXPO HALL or challenge other delegates and the ESPC team to some fun games in the Community Area.
Not enough? Be sure to join the EXPO drinks on Tuesday evening or enjoy a magical night at the sell-out ESPC18 PARTY: A NIGHT AT THE CIRCUS.

5. SHARE with your Team

Schedule a meeting post conference to share your key learnings with your fellow co-workers. Impress colleagues with your advanced knowledge while maximizing value for your company. Share your inspiration and make plans to implement what you learned.

Still undecided about attending The leading European SharePoint, Office 365 & Azure Conference? Visit 10 REASONS TO ATTEND ESPC18 to see why you need to be there.

BOOK YOUR TICKET today and use coupon code ESPC18SPK to receive a €100 discount.

Wednesday, October 17, 2018

Using pnpjs v1.2+ with Internet Explorer 11

man and woman lit the two lighters they are holding

When pnpjs v1.2 was released the PnP team made a wise decision to remove support for IE11. The decision to drop support for IE11 means some of the functions will fail if you use pnpjs in for example a SharePoint Framework component, and the user is using Internet Explorer 11.

The direction is wise in my opinion because IE11 is 5(!) years old, and from a programmers perspective it lacks features you would expect on a modern browser. As an example, how old is your phone? Most likely the browser on your phone is a lot better than IE11. In this day and age 5 years is an eternity.

The issue comes down to several points:

  • Older windows versions have IE11 as the default browser
  • Your IT department might not want to support a 3rd party browser
  • If you are running Windows 10 (now 3 years old), IT might have kept IE11 as the default browser because it’s there
  • You have some legacy plugins or LOB application only working with IE11

All of these might be valid points, but if you have clout, push IT to rid themselves of IE11, and switch it out with Edge, Chrome, Firefox or some other browser.

Unfortunately, reality is that companies will continue to use IE11 as long as it’s shipped with Windows, so come on Microsoft – kill it already!

So how do you backwards proof your application if you are using pnpjs and IE11 is a requirement? Take a look at the updated official documentation https://pnp.github.io/pnpjs/documentation/polyfill/.

Previously you would have to add manual polyfills as mentioned in this github issue, but this is now made easier.

Add a reference to @pnp/polyfill-ie11 with install --save @pnp/polyfill-ie11, and anywhere in your code where you import pnpjs, add

import "@pnp/polyfill-ie11";

If using SearchQueryBuilder, then you need and additional import statement – but read the docs and you’ll be fine.

Photo by Element5 Digital at Unsplash.

Thursday, September 27, 2018

Workaround for removing a deep folder structure in SharePoint

Deep water signage

I had a client which were not able to delete a deep folder structure from SharePoint which I’m guessing was synced in via OneDrive.

The error they got when trying to delete anything in the structure was “Error Code: 6404” – not a very descriptive error.

image

I tried all sorts of API’s, but having worked with SharePoint and Windows for a while I figured this had to do with a total path being too long, and I was correct.

In the end I renamed every single folder to “a”, just one character, and then the total path length was short enough for SharePoint Online, and the structure deleted nicely.

Photo by Rosie Kerr on Unsplash

Example of wrapper to ease usage of Graph calls in SPFx

silhouette of trees and purple lightning

Waldek Mastykarz wrote a good post about not passing the web part context all around your React components, which is good advice. And as Waldek pointed out after reviewing my code I pass the full context and not just the GraphClient. So ideally, passing just what you need is better, but I’m lazy at times :) And it gives you the reader an opportunity to improve my code :)

I tend to create static helper classes, and here’s one approach to ease calling Graph API’s throughout your solution.

The wrapper class is quite simple, and I’ve created helper methods for GET, POST, PATCH, DELETE.

To use this you would first initialize the class in your main web part code.

public async render(): Promise<void> {
   await MSGraph.Init(this.context);
   ...
}

and somewhere in your code if you wanted to get Group data for a group you could use something like this:

import { MSGraph } from '../services/MSGraph';

...

let groupId = this.props.context.pageContext.legacyPageContext.groupId;
let graphUrl = `/groups/${groupId}`;
let group = await MSGraph.Get(graphUrl);

Photo by Jeremy Thomas at Unsplash

Monday, September 10, 2018

An approach to search for a URL within a page or document in SharePoint

image

The Search Explained Yammer network is a great place to ask the weird and quirky search questions. Unfortunately it’s not indexed by Google, so answers there will not benefit everyone – which is why I’m writing this post.

A couple of days ago someone posted a question if it was possible to find pages in SharePoint which contain a specific link. The need was to identify broken links. Use-case can be if you rename a file, and want to find all pages linking to that file before renaming – to make sure they still point correctly.

This post will show you one approach which works, and if you have a better suggestion, please let me know.

Question is; how can you go about finding a page with the link https://contoso.sharepoint.com/sites/collection/site/library/document.docx as part of the content?

Monday, September 3, 2018

Puzzlepart presents the modern flexible Divider web part

Did you ever think the Divider web part for modern pages was too restrictive? Maybe you wanted to cross that divide with a wider one, maybe you wanted to separate with colors? Don’t worry – now you can!

The sharing minds of Puzzlepart hereby introduce the flexible divider web part which allows you to set both the width and the color!

preview

Get the web part code from the link below, or contact us if you want assistance on a pre-compiled tenant wide distributed web part.

https://github.com/Puzzlepart/spfx-solutions/tree/master/Pzl.Part.Divider

Thursday, August 30, 2018

Issue when executing PowerShell scripts with characters outside of A-Z

I have a PowerShell script in which I pass a parameter to command containing the Norwegian character ø, where the command sets a value on a web page.

When checking the result, it looks like this:

Hvem gjør hva

Clearly an encoding issue. My .ps1 file was saved in UTF-8, and to make it work I changed it to UTF-8 with BOM (byte order mark). This way PowerShell can correctly detect the script as being in UTF-8 and encode the characters correct. To change encoding use for example VSCode or Notepad++.

Summary

If you have characters outside of a-z in your scripts, be sure to save them as UTF-8 with BOM to avoid any encoding issues.

Cover photo by Krisitan Strand at Unsplash

Tuesday, August 28, 2018

Gotcha when adding Office UI Fabric React to SPFx



(Update for SPFx v1.7 - 2018-11-09)
This post is still valid for SPFx v1.7

When installing a reference to Office UI Fabric React make sure to run

npm i office-ui-fabric-react@lts --save

and not

npm i office-ui-fabric-react@latest --save

Lts is the latest stable version, which currently is v5.122.1 and in this case compatible with React 15 which is what SPFx uses. The latest version is 6.57.0 which require React 16, and won’t build with SPFx.

Stable photo by Ryan Yeaman at Unsplash

Monday, August 27, 2018

Modifying terms using app-only tokens in SharePoint – undocumented work-around


Photo by Alekzan Powell at Unsplash

In a rage of fits yesterday where I was running a PowerShell script against SharePoint Online with an account using multi factor authentication – which just don’t work reliably due to the use of login via web browser I decided to use app-only authentication instead.

I used the following permission manifest which should ensure god rights, right?

<AppPermissionRequests AllowAppOnlyPolicy="true" >
  <AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="FullControl" />
  <AppPermissionRequest Scope="http://sharepoint/taxonomy" Right="Write" />
</AppPermissionRequests>

But since I’m dealing with modifications to terms in this script, that quickly broke down. More rage, more fits!

Reading https://msdn.microsoft.com/en-us/library/office/mt210897.aspx?f=255&MSPPError=-2147217396#sectionSection0 states:

You can't use the app-only policy with the following APIs:

  • User Profile

  • Search

  • Taxonomy (this only applies to scenarios that write to the managed metadata service)

Wednesday, August 22, 2018

An even better bundle optimization method for SPFx using webpack dynamic imports


Photo by Rose Elena at Unsplash

In my last post I ventured into how you dynamically can load script resources in your SPFx web part or extension. Typically you might have parts only needed in edit mode, or parts only used in certain view scenarios. By not including everything in the SPFx bundle you will reduce loading time and page bootstrapping of your solution.

For example, if you use a lot of Office UI Fabric components or an external library like moment, then your overall bundle size, or downloaded .js file increase a lot. If those components are not always needed, loading them dynamically at will is a better solution.

And, it’s so easy! SPFx uses web pack to create the bundle, and webpack allows for something called dynamic imports. And this is such a golden nugget – sitting there without anyone knowing :)

Tuesday, August 21, 2018

An adventure into optimizing SharePoint Framework runtime bundle sizes

image

(See https://www.techmikael.com/2018/08/an-even-better-bundle-optimization.html for an even better solution)

When I wrote the Modern Script Editor web part I went with using Office UI Fabric React (ouifr) for the editor UI. The web part bundle yields a zipped script file of 84KB when used on a page. Not that much really, and it will be cached in the browser. But most of the bundle size is due to the use of ouifr in the edit experience of the web part – not needed in view mode for a page.

Thus I’ve had a nagging feeling working on my mind for a while, and it occurred to me; why can’t I have the editor experience separate from the run-time experience?

And you can!! which I will explain how further in this post.

The result is that the updated web part now will download 4KB zipped on run-time instead of 84KB. A whopping 95% decrease. The editor experience will be another 141KB, which is more in total than before, but this only happens when you edit the page and web part – certainly a good trade off.

Monday, August 6, 2018

Highlighting which page is the welcome page in a site

A week ago Joanne Klein posted a request on twitter where she asked if it was possible to easily see which page is the home page or welcome page of a site. In a library with hundreds of pages, this can be quite useful indeed.

image

Technically the information about which page is the home page is stored as property on the root folder of the web (almost a mouthful there), which translates to that it’s not stored on the page it self, thus not “easily” set by adding a column.

The developer in me figured I could whip up a quick custom field renderer for the modern page library and have this working in a matter of minutes. Turns out, it’s not that easy. (A field renderer is a piece of code which shows a column value in any way you decide, instead of the default way – for example add a red background color.)

Either way, head over to https://github.com/Puzzlepart/spfx-solutions/tree/master/Pzl.Ext.HighlightHome if you want to download and install a solution which does highlight the home page for you. Install instructions are on that page as well.

image

Friday, July 27, 2018

Getting a sticky header for your modern SharePoint lists and libraries

image
Photo by Carson Arias on Unsplash.

[Update - June 2019]
The download link and code has been removed as this feature is rolling out. It's currently in TR tenants and should make it's way to GA in not too long.

----
If you have a list or library with many columns and items it becomes hard to navigate list when the header row scrolls out of view. Basically you are loosing context. Excel has had the ability to freeze the top header row for forever, and having this in modern lists and libraries would be extremely useful.

There is a user voice request for this at https://sharepoint.uservoice.com/forums/329214-sites-and-collaboration/suggestions/16077640-freeze-column-headers which you can upvote and maybe we will get it sooner rather than later.
Or………

Wednesday, July 25, 2018

Using Microsoft Graph to get a PDF preview of a file in SharePoint by file path

The viewfinder of a camera shows a photo of the sunset.
Photo by Glenn Carstens-Peters on Unsplash

There are multiple ways to get a PDF version of a file, so I figured I’d show how you via a path to a file in SharePoint can use the Microsoft Graph API to get a PDF version of that file. I’ll be using the Graph drive item conversion API for this.

A sample URL could look something like this: https://contoso.sharepoint.com/sites/asite/FooLib/lala/Document.docx

[Update]

After posting the question on Stack Overflow I received an answer from Vadim Gremyachev which takes it down to one API call.

Basically he clued me onto how you can create a sharing token for the item URL which is actually the file id. Code for this is listed in the Graph Sharing API docs.

First you base64 encode the URL, replace some characters and prefix with u!, then access the files via the /sharing API. The below code is using PowerShell to construct the token.

$url = 'https://contoso.sharepoint.com/sites/asite/FooLib/lala/Document.docx'
"u!"+[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($url)).TrimEnd('=').Replace('/','_').Replace('+','-')

u!aHR0cHM6Ly9jb250b3NvLnNoYXJlcG9pbnQuY29tL3NpdGVzL2FzaXRlL0Zvb0xpYi9sYWxhL0RvY3VtZW50LmRvY3g

Armed with the token the result API call is:

https://graph.microsoft.com/v1.0/shares/u!aHR0cHM6Ly9jb250b3NvLnNoYXJlcG9pbnQuY29tL3NpdGVzL2FzaXRlL0Zvb0xpYi9sYWxhL0RvY3VtZW50LmRvY3g/driveItem/content?format=pdf

[Original post]

In order to get to the actual file two API calls are needed, one to fetch the drive (library) id, and one to fetch the file.

Note: This solution will not work on the root site collection as I make assumptions on the number of parts of a URL. The following file formats are supported: csv, doc, docx, odp, ods, odt, pot, potm, potx, pps, ppsx, ppsxm, ppt, pptm, pptx, rtf, xls, xlsx.

Deconstructing the file URL

Splitting the URL on slashes we get the parts needed to get the id of the document library and the id of the file.

0 https:
1
2 contoso.sharepoint.com
3 sites
4 pub
5 FooLib
6 lala
7 Document.docx

Part 2 is the tenant hostname, part 3+4 is the site path, part 5 is the document library, and part 6 and out is the item path relative to the document library.

Getting the drive id (id of document library)

Using the sample URL above we combine the sites and drives API’s in one query:

/v1.0/sites/{hostname}:{server-relative-path}:/drives

resulting in the following query where we select id and url

https://graph.microsoft.com/v1.0/sites/contos.sharepoint.com:/sites/asite:/drives?$select=id,weburl

The output of this call are all the libraries in the site.

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives(id,webUrl)",
    "value": [
        {
            "id": "b!H11aFSof8062NsPf4rr-qE3OKQpUIjVEp7PzqdeT_psgYyKuXH2VR7fGsvWPyBOt",
            "webUrl": "https://contoso.sharepoint.com/sites/asite/Documents"
        },
        {
            "id": "b!H11aFSof8062NsPf4rr-qE3OKQpUIjVEp7PzqdeT_pv8T5clDnpiRZq2uVmXgGRU",
            "webUrl": "https://contoso.sharepoint.com/sites/asite/FooLib"
        },
        {
            "id": "b!H11aFSof8062NsPf4rr-qE3OKQpUIjVEp7PzqdeT_psUQF8PSnx9T7aXwvRalLc_",
            "webUrl": "https://contoso.sharepoint.com/sites/asite/PublishingImages"
        },
        {
            "id": "b!H11aFSof8062NsPf4rr-qE3OKQpUIjVEp7PzqdeT_pv01hj6qcWyR5wulob7Lk7-",
            "webUrl": "https://contoso.sharepoint.com/sites/asite/Pages"
        },
        {
            "id": "b!H11aFSof8062NsPf4rr-qE3OKQpUIjVEp7PzqdeT_pvEaXdch-3DToEk0qR4g-xx",
            "webUrl": "https://contoso.sharepoint.com/sites/asite/SiteCollectionDocuments"
        },
        {
            "id": "b!H11aFSof8062NsPf4rr-qE3OKQpUIjVEp7PzqdeT_ptwBh2OaBQOTbJMXT5jLKwi",
            "webUrl": "https://contoso.sharepoint.com/sites/asite/SiteCollectionImages"
        },
        {
            "id": "b!H11aFSof8062NsPf4rr-qE3OKQpUIjVEp7PzqdeT_pv-q5N0D8gWSLB-0MY7_RS3",
            "webUrl": "https://contoso.sharepoint.com/sites/asite/Translation%20Packages"
        }
    ]
}

Ideally you would use a $filter query to pick out just the library you want, but this is not supported for the drives endpoint, so you need to post-filter yourself.

By filtering out the item which has a webUrl  matching part 2,3 and 4 combined you have the library you are looking for.

Getting the PDF URL for the file

With the id of the document library in hand, it’s time for the next query which will return the URL of the PDF version in a 302 Location header.

/v1.0/drives/{drive-id}/root:/{item-path}:/content?format=pdf

Using the drive id from the previous call together with the document path I end up with the following URL

https://graph.microsoft.com/v1.0/drives/b!H11aFSof8062NsPf4rr-qE3OKQpUIjVEp7PzqdeT_pv8T5clDnpiRZq2uVmXgGRU/root:/FooLib/lala/Document.docx:/content?format=pdf

If you look at the Location header in the returned response you will find something similar to:

https://northeurope1-mediap.svc.ms/transform/pdf?provider=spo&inputFormat=docx&cs=N2FiNzg2….

This is a pre-authenticated URL which can be called directly from anywhere without the need to logging in, and the URL is valid for a few minutes only.

Friday, June 29, 2018

Using PnP PowerShell to inspect the crawl log in SharePoint Online

One of the lesser know features for SharePoint Online is the ability to look at the crawl log. For on-premises SharePoint, scanning the crawl log is something any search troubleshooter knows how to do, and something I’ve often heard is an ask for SharePoint Online.

A typical scenario is someone asking why their file does not show up in search, or why a user profile hasn’t been updated in search. The crawl log won’t solve these issues, but might give you hints and insights for further troubleshooting as you can see any warnings or errors, and see at what time the item in question was last crawled.

Over two years ago I created a SharePoint App which allows you to search the crawl log and trigger re-indexing (https://store.office.com/en-us/sharepoint-online-search-toolbox-by-puzzlepart-WA104380514.aspx), but I figured the time was right to share this with the world – hence the June release of PnP PowerShell introduced the new cmdlet Get-PnPSearchCrawlLog. But if you fancy a UI, the app is still there :)

selected image

Test it for yourself or take a look at the demo I did yesterday at the PnP sig call.

https://youtu.be/BaUfhFYC2tQ?t=40m35s

Tuesday, June 12, 2018

Dynamically load a web part from another web part

I coded a proof of concept last week on how to load a SPFx web part from another web part which I plan to use as pattern for display templates for a search web part I’m planning. By using SPFx parts as render templates we get better control of the code, and avoid script injection on the page.

I figured this approach might be useful for other scenarios so here’s the code to play with :)

The POC loads up two instances of the Modern Script Editor web part, and sets data in it. Which means the modern script editor web part has to be installed on the site you are testing on. Or replace with any of the oob web parts and set the correct properties.

Issues I haven’t gotten to yet as they are not a concern for my scenario are:

  • How to access web part properties of the dynamic loaded web parts in edit mode – can be worked around if the web part has a custom edit UI
  • How to persist the web part data and store it in the main web part – take a look at the serialize method of the ClientSideWebPartManager.
  • The text web part is a special kind of web part, so not sure how to dynamically instantiate it

Full sample can be found at https://github.com/wobba/spfx4fun/tree/master/DynamicLoad

import * as React from 'react';
import styles from './HelloWorld.module.scss';
import { IHelloWorldProps } from './IHelloWorldProps';
import { Guid } from '@microsoft/sp-core-library'
import { ClientSideWebPartManager, IWebPartManagerContext, IWebPartData } from '@microsoft/sp-webpart-base';
import { DisplayMode } from '@microsoft/sp-core-library';

import { IClientSideWebPartManifest } from '@microsoft/sp-module-interfaces';

let _webPartManager: ClientSideWebPartManager;
let _sampleIdOne = "mAdcOW" + Guid.newGuid().toString();
let _sampleIdTwo = "mAdcOW" + Guid.newGuid().toString();
export default class HelloWorld extends React.Component<IHelloWorldProps, {}> {

    public async componentDidMount(): Promise<void> {
        _webPartManager = new ClientSideWebPartManager(this.props.context.host);
        await _webPartManager.fetchWebPartManifests(); // Ensure all manifests are available
        this.addData();
    }

    private async addData() {
        // local webpart properties - in this case props for the modern script editor webpart
        let props = {
            script: "<div>Foo</div>",
            title: "The Modern Script Editor web part!",
            removePadding: false,
            spPageContextInfo: false
        }
        await this.loadWebPart("ScriptEditorWebPart", document.getElementById(_sampleIdOne), props);
        await this.loadWebPart("ScriptEditorWebPart", document.getElementById(_sampleIdTwo), props);
    }

    private async loadWebPart(alias: string, domElement: HTMLElement, webPartProperties: any) {
        let manifests = _webPartManager.getWebPartManifests();
        for (let i = 0; i < manifests.length; i++) {
            const manifest = manifests[i];
            if (manifest.alias === alias) {
                let instanceId = Guid.newGuid().toString();
                let wpManifest: IClientSideWebPartManifest<any> = manifest as IClientSideWebPartManifest<any>;
                let wpData: IWebPartData = {
                    id: wpManifest.id,
                    instanceId: instanceId,
                    title: "",
                    dataVersion: "1.0",
                    properties: webPartProperties
                };

                // Specify any as webpartLoadExtraLogInfo is not defined on the interface and has to be present
                let initialize: IWebPartManagerContext & any = {
                    domElement: domElement,
                    instanceId: instanceId,
                    manifest: wpManifest,
                    displayMode: DisplayMode.Read,
                    webPartData: wpData,
                    webpartLoadExtraLogInfo: {
                    }
                };
                await _webPartManager.loadWebPart(initialize);
            }
        }
    }

    public render(): React.ReactElement<IHelloWorldProps> {
        
        return (
            <div className={styles.helloWorld} >
                <div className={styles.container}>
                    <div className={styles.row}>
                        <div className={styles.column}>
                            <span className={styles.title}>Dynamic loading!</span>
                            <span id={_sampleIdOne}></span>
                            <span id={_sampleIdTwo}></span>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

Monday, May 28, 2018

How to reset a modern home page using PnP PowerShell


Photo by Nikita Kostrykin at Unsplash

Here’s a short snippet which will reset any modifications done to a modern home page back to the default layout.

Basically you clear out the CanvasContent1 field which stores the page layout and contents.

Connect-PnPOnline https://<tenant>.sharepoint.com/sites/mysite
# Get welcome page url
$web = Get-PnPWeb -Includes WelcomePage
# Load the page
$file = Get-PnPFile -Url $web.WelcomePage
# Get the page's item
$item = $file.ListItemAllFields
# Load the item id
Get-PnPProperty -ClientObject $item -Property Id
# Clear the content to reset
Set-PnPListItem -List SitePages -Identity $item.Id -Values @{"CanvasContent1"=$null} -SystemUpdate

Quickly clear Followed sites using PnP PowerShell

In my dev tenant I do a lot of testing with Groups and sites, and this has the effect that my demo user is following a lot of, often with the same name as seen in the image below.

image

The followed sites are actually stored in a list named Social in your OneDrive. This list was introduced with SharePoint 2013, and still alive and kicking. You can access followed sites from the following URL:

https://<tenant>-my.sharepoint.com/personal/<user site>/Social/Sites.aspx

This list also tracks followed documents and people, but that’s not the focus of this post.

First connect to your OneDrive using PnP PowerShell, then execute the code below to remove all followed sites, and be sure to set the correct URL in the first line.

$followedSitesUrl = "/personal/<user site>/Social/Private/FollowedSites"
$sites = Get-PnPListItem -List Social -Query "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FileDirRef'/><Value 
Type='Text'>$followedSitesUrl</Value></Eq></Where></Query></View>"
$sites |% { Remove-PnPListItem -List Social -Identity $_.ID -Force }

Once complete, the list is now empty.

image

Tuesday, May 22, 2018

Two SPFx manifest settings you might not be aware of

image

If you take a look at the manifest schema for a SPFx web part there are a couple of settings you might want to take a look at.

hiddenFromToolbox

If hiddenFromToolbox is set to "true", the web part will not be visible in the modern SharePoint toolbox. Very useful for web parts you provision automatically on pages, but don’t want users to add themselves.

supportsFullBleed

If supportsFullBleed is set to "true", the web part can be added to a full page width zone on a modern page in a communication site, spanning from the left margin to the right margin without any white space.

Friday, May 11, 2018

Caution when using $expand with Microsoft Graph

Using the $expand parameter with calls to the Microsoft Graph is very handy. In one API call you can retrieve both the object itself and additional properties.

Two examples are fetching a user and the direct reports, or a group and it’s members.

https://graph.microsoft.com/beta/users/061353c3-af75-4767-9b19-a5bceed85f53?$expand=directReports

https://graph.microsoft.com/v1.0/groups/79958190-024b-4c62-ab55-65dc9a066cac?$expand=members

image

The caution is that when you expand a property which has a collection of values, you will only get the first 20 items returned. This means that if you work in an organization with more than 20 people in it, you should not use $expand if you need all the values, but resort to two calls instead, one for the item, and one for the property you want to expand.

Summary

While using expand is very handy, it’s almost always better to break it into two API calls to avoid having issues if you can expect more than 20 items.

Tuesday, May 8, 2018

How to get the list item from a file URL using PnP PowerShell

image
Photo by Karly Santiago at Unsplash

This is one of the snippets I always forget, but which is very handy in cases where you have the absolute URL to an item in SharePoint. The magic is really line 6 which uses the static method WebUrlFromFolderUrlDirect to get the web URL of the file, so that you can connect properly.

[Updated 2021-01-19 to support "People with existing access" sharing URL's]

$uri = [Uri]'https://contoso.sharepoint.com/sites/foo/bar/Shared%20Documents/mikael-is-cool.docx'.replace(":w:/r/","")
$uri = [Uri]$uri.OriginalString.Replace($uri.Query,"")
# Connect to the root site, or any other site
Connect-PnPOnline -Url ($uri.Scheme+'://'+$uri.Host)
$ctx = Get-PnPContext
# Get the web url for the file
$webUrl = [Microsoft.SharePoint.Client.Web]::WebUrlFromFolderUrlDirect($ctx, $uri)
Connect-PnPOnline -Url $webUrl
$fileItem =  Get-PnPFile -Url ([System.Web.HttpUtility]::UrlDecode($uri.AbsolutePath)) -AsListItem

Sunday, May 6, 2018

Locating where a term set is used in SharePoint using search

Joanne Klein asked on Twitter if there is a way to get all places where a specific term set is used in SharePoint.

image

One way would be to iterate all site collections and check if the term set was present in the Hidden Taxonomy List, which stores all used terms on a site collection (and if you have no idea what that is, that’s ok as well).

image
Hidden Taxonomy List at /Lists/TaxonomyHiddenList/AllItems.aspx

Another option which is the solution I proposed, is to use search. Of course you need to have read access to the items where the term set is used for it to be 100% accurate as well items using terms from a term set has to be present in the search index.

Friday, May 4, 2018

Use Microsoft Flow to implement approval of site pages


Photo by Zachary Nelson at Unsplash

Again I’m late to the party, but Microsoft has released an action to Flow called “Set content approval status”. This action enables you to add content approval not only to list elements and documents in SharePoint, but also to news pages.

Microsoft has talked about content approval for ECM scenarios with communication pages for a while, but until a proper UI is in place, you can get started today!

This is how.

Thursday, May 3, 2018

Addendum to Chaks’ post “Deep dive into ‘Get items’ and ‘Get files’ SharePoint actions in Microsoft Flow”

Chaks recently wrote a post where he explained the difference between the two Microsoft Flow SharePoint actions Get items and Get files (properties only).

Behind the scenes they are both calling the following undocumented service which seems to wrap the regular OData call:

/_api/SP.APIHubConnector.GetListItems(listName='MyList',queryOptions=@q)?@q=''"

Good news is you can use both actions interchangeably. If you want to get the properties for a document library using the Get items action simply pick Custom value in the dropdown and enter the title or id for your document library and it works just fine (been using this already a while).

image

So, to me, having the Get files (properties only) action seems unnecessary, but for some users it might be easier to understand with two different actions targeted towards lists or libraries.

image

Thursday, April 26, 2018

The SharePoint Properties Pane (successor to DIP) is available for SharePoint 2013

Last year at Ignite we were all psyched that Microsoft gave us a replacement for the old Document Information Panel (DIP) in Word which allowed us to set metadata stored in SharePoint columns. DIP disappeared with Office 2016 (and you had to edit properties in the info settings page instead), and finally we got a replacement. However, it only worked for documents stored in SharePoint Online.

I did a proof on concept of this with a colleague last year as well, so it was just a matter of time until it was properly release.

The announcement slipped past me as there has not been a lot of whoo hah around it. Reading the release notes for the December 2017 CU for SharePoint 2013 it states:
  • Enables the new Document Information Panel feature that's visible in Word 2013.
Maybe a bit cryptic, and I haven’t tested if Word 2013 shows the SharePoint Property Pane, but at least Word 2016 shows it just fine against a document stored in SharePoint 2013.

So, patch away and enjoy SharePoint properties once again in Word!

Word SharePoint Properties Panel.PNG

Tuesday, April 24, 2018

How to run AzureAD PowerShell commandlets in Azure

I have a PowerShell script which today uses AzureAD commandlets to perform some write operations in Azure AD. This script is to be run on a schedule, and where better to run this than in Azure. It could be as a web job or as an Azure Function.

When running in an app service we cannot use interactive login, but have to use the connect signature below which takes an ADAL app id and a certificate:

Connect-AzureAD –TenantId <tenantId> –ApplicationId <appid> –CertificateThumbprint <thumbprint>

This means we have to create and ADAL app which accepts a certificate, as well as make sure we can access the certificate from the app service.

For this tutorial I’ll go with an Azure Function, but the steps are pretty much the same.

Pre-requisite

Install the AzureAD or AzureADPreview command lets on your local machine.

Steps covered

  • Create a self-signed certificate
  • Create an ADAL app
  • Grant the ADAL app access to write to AAD
  • Create an Azure Function
  • Load Azure AD PowerShell in an Azure Function
  • Connect to AzureAD using an ADAL app and a certificate

Sunday, April 22, 2018

Sneak peek at managed navigation for HUB sites

A granite mountain peak rising up above pink-hued clouds
Photo by Cédric Servay at Unsplash

One of the cool features of the new hub sites is that associated sites inherit the navigation of the hub. This means you have one place to configure navigation, and you don’t have to resort to any of the numerous custom solutions out there to solve this. Hub sites makes it very easy to create small hierarchies of sites with a common navigation structure.

A lesser known fact is that the hub navigation also support managed navigation, a popular way to configure navigation since its inception in SharePoint 2013, and something constantly asked for in modern sites.

This post will show that you can achieve it today, but you should probably wait until it’s properly supported.

Thursday, April 12, 2018

Expose values from an existing InfoPath field to a SharePoint field


Photo by adrian on Unsplash

Ok, I know InfoPath is not the future and all, but I happen to have one client which has an old InfoPath solution for reporting incidents at their facility. I have previously migrated this from SharePoint 2007 to 2013, which involved some XML manipulation in the process, and I did spare you a blog post on this :-)

Either way, the lists of incidents which goes back years have now been hooked up to PowerBI via the on-premises gateway, so the customer is slowly taking the leap to the cloud.

And, turns out, the date field which has the date of the incident was never exposed as a SharePoint field, a field which is pretty nice to report on for incidents.

I fired up SharePoint designer, promoted the field in question and re-published the InfoPath form. This ensured all new items would have a date in the incident date field, but all existing items were still blank. So how could I in the easiest way possible get the value from the XML files promoted to the SharePoint field? Turns out it was very very very easy.

It was a matter of looping over all list items and running SystemUpdate() on them. This ensured modified date and modified by fields were not changed, but the value got populated.

Below is my PnP PowerShell snippet which saved the day.

Get-PnPListItem -List "Incidents" |% { $_.SystemUpdate();$_.Context.ExecuteQuery() }

Wednesday, April 11, 2018

Free status bar extensions for modern SharePoint sites

Did you think we were being lazy over at Puzzlepart? Think again. This time we give you a status bar top extensions.

statusbar

Get the code at https://github.com/Puzzlepart/spfx-solutions/tree/master/Pzl.Ext.StatusBar

The above image shows two notifications, one which checks if the Office 365 Group support external member or if the site allows sharing with external users. The other highlights a classification setting if it’s a specific value, in this case sites with classification Confidential or above will show a status message.

Technically it consists of three extensions, one base extension doing the rendering, and then you can add any number of other extensions which render a message based on the logic you decide. If there are nothing to render, then the status bar will not render.

I’m not saying the communication between the parts is the most graceful one, but it’s a pattern we are trying out – and it works, and you can use the base renderer with your own logic. Take a look at the two samples provided and you should figure out how to create your own. The clue is the messageId parameter which has to be the same for all extensions, to make them aware of each other.

Get the code at https://github.com/Puzzlepart/spfx-solutions/tree/master/Pzl.Ext.StatusBar

Tuesday, April 10, 2018

Working with Hub Sites and the search API


Photo by Sunaina Kamal at Unsplash.

Hub sites are a nice way to create a virtual two level site hierarchy without using sub sites. An administrator will nominate a site as a hub site, and then other sites can associate themselves to this hub. By associating a site to a hub the site will inherit the navigation and the visual look of the hub itself, ensuring a consisting look and feel. Also items from associated sites will surface in search at the hub level (as long as you have read access to the item).

image

Note: The hub site feature is currently in preview and only available for target release tenant at the time of writing.

After playing with hub sites you might want your favorite developer to create something for your hub sites, and this is where the search API is handy.

Thursday, March 29, 2018

Quick tip: easily test SharePoint Framework web parts on modern pages (addendum to Waldek’s post)

image

Did you know that you can easily test your SharePoint Framework web parts on modern pages?

If there’s one guy who know, it’s my friend Waldek Mastykarz. Today he had a post outlining how you can debug/test SPFx web parts on a real modern page, not the SharePoint workbench.

Wednesday, March 28, 2018

Optimizing meshing with Cisco Meraki access points

image

I have had a Cisco Meraki MR-33 hooked up for a little while, which is positioned pretty centrally in an L shaped space. The issue is that the building is old with lots of brick walls. In the far room of the long leg of the L there is about 2 meters of space which gets pretty spotty connection. Not a huge deal, but enough to irritate :)

Setting up a second access point via cable is not a viable option so I decided to mesh two access points instead. The setup was easy, but the throughput was not amazing, averaging around 15mbit/s, and lower. You might think this is ok as we’re meshing, but the good thing is that it can be improved.

Note: Read the Meraki guide Manually Changing Channels in a Mesh Network for information on how you can change the channel used for meshing.

By default when you have auto channels for both the 2.4GHz and the 5Ghz radio, the 5GHz channel will be set to the same channel for both devices, and this is used for meshing. Having band steering on, where clients also use 5GHz, this will greatly reduce the speed.

What I did was this.

  • I set a dedicated channel for the 2.4GHz radio – to allow meshing to happen on the 2.4GHz radio, which also travels better though the brick walls.
  • I set the 5Ghz radio to automatic.
  • I use band steering, leading clients to the 5GHz radio.

This setup “ensures” clients use 5Ghz, while the mesh traffic have the full bandwidth itself on the 2.4GHz radio. Now my throughput is pretty consistent around 55mbit/s.

image

Office 365 logo kit available at Fasttrack for partners/customers

Ever in the need to use Office 365 icons and wonder how they can be used? Head over to https://fasttrack.microsoft.com/dl/brandingkit (requires login) and download the Microsoft Office 365 Branding Toolkit today.

The downloaded zip file has icons in different formats. Below are samples of the 256x256 icons, and the file only contains .png files.

image

image

Monday, March 26, 2018

Updated Modern Script Editor Web Part with fix for AMD modules and exposing _spPageContextInfo

image

The web part haven’t change much, but the following configuration options are now available:

  • Keep or remove padding on the web part zone – useful if you have script which does not output any markup.
  • Set the _spPageContextInfo variable – useful if you have old scripts using this variable on classic SharePoint pages.

I have also fixed the code so that it won’t fail when loading AMD module scripts – meaning the scripts will not detect themselves as module scripts, but load globally instead.

You can get the code from https://github.com/SharePoint/sp-dev-fx-webparts/tree/master/samples/react-script-editor.

SharePoint Query Tool v2.8


Image by Emily Morter on Unsplash

This is a short one, and not much has changed. Basically I removed the old browser based SharePoint Online login method as it caused too much friction on Windows 10 machines. And I fixed an issue where all properties did not show when using the new SharePoint Online login method.

Get v2.8!

Friday, March 23, 2018

Two approaches to applying a modern theme using PnP


Photo by Ash Edmons on Unsplash

Modern sites are no longer using the old theming engine directly with .sptheme, .spcolor and .spfont files. Instead you can use the Theme Generator tool to get your colors the way you want them, and this is what this post will focus on, how you can automatically set the right colors using PnP. The post has two samples, one using PnP PowerShell and one using a PnP Provisioning template.

Monday, March 19, 2018

A workaround for saving hi-res photos from PowerApps to SharePoint

Saving photos or images from PowerApps to SharePoint is not easy, but there are workarounds using for example Flow to get this to work as I’ve written about previously. The caveat with this approach is that when using the camera control you won’t get full resolution on the images you take, but a scaled down version – and adding Flow to the mix increased complexity.

With the recent release of supporting attachments with SharePoint lists in PowerApps it’s now possible to get those high resolution photos into SharePoint. But, it’s not straight forward. Even though it’s possible you should think it through before going full on production with this.

Note: This post is written based on testing on iOS.

Uploading photos is a common ask when using PowerApps on mobile device. You might create a reporting application of sorts which supports adding photos as documentation. My first thought was to utilize the new attachment support, pick the camera as input and be done with it. Turns out I should stop believing in fairy tales when a feature is just released :). When tapping the “Attach file” link, you get a dialog to browse your iCloud Drive, not an option to tap into the camera. Which makes sense as you need an attachment filename. This means we cannot use the default add attachment functionality.

20180318_124151000_iOS

What I came up with was using the “Add picture” control with a custom collection, and then binding the forms attachment control value to this collection. You also need to reset the form after you modify the collection in order for the change to be picked up in the control (which is needed for it top be submitted). The reset has a timing issue, so I had to add a timer control which reset’s the form every 1 second. It’s all in a days works of duct tape.

Oh well.. let’s build the application, and you will see for yourself.

Friday, March 16, 2018

How to display images from a SharePoint library in PowerApps

[Update: As mentioned in the comments by Paul Culmsee, this only works in the web version of PowerApps - not on devices. To make it work on devices take a look at his posts for a proxy workaround]

A while back I wrote a post about how to save images from PowerApps to SharePoint via Flow. Today  I got a comment asking how you can show images sored in a SharePoint library in a PowerApp. Turns out it’s not hard at all.

I first created a new document library named “Images” in a SharePoint site and uploaded two images.

image

Within your PowerApp add a new data source, and manually type in the name to the library containing your files, in my case “Images” and hit “Connect”. The manual typing is the crux to make this work.

image

Next add a gallery to your app and bind it to the Images data source. For the Image control, change the binding to be ‘{Link}’ and you should see your images showing up in the gallery.

image

Happy PowerApping!