SharePoint 2019 Solution: “Sorry, apps are turned off. If you know who runs the server, tell them to enable apps.”

Photo by Artem Beliaikin from Pexels

Without an App Catalog and a setting enabled, your users may run into the following error when attempting to access the SharePoint Store from the “Add an app” dialog:

“Sorry, apps are turned off. If you know who runs the server, tell them to enable apps.”

If you’ve run into this issue and are a farm admin, you can enable the app store and ability in SharePoint 2019 by following these steps. If you’ve already created the App Catalog site collection, skip to step 4.

1. Log onto your central admin server and open central admin

Click to enlarge

2. Choose Apps > Manage App Catalog. Make sure the Web Application shown is the correct web application then click OK to create a new App Catalog (or enter a URL for one if you’ve already created one)

Click to enlarge

3. Set the App Catalog site name and description, URL, admin, and then end users who should see apps in the catalog.

Click to enlarge

4. Once you have an App Catalog, go back to Apps > Configure store settings.

Click to enlarge

5. Confirm the Web Application shown is the correct web app, then change App Purchases to Yes. Save your changes.

Now when users who were granted access to view apps in the store choose SharePoint Store from the “Add an app” dialog, they’ll be able to get marketplace apps as well.

Click to enlarge

Hide the Browse and Edit buttons and/or the Share, Follow, and Focus/Full-Screen buttons from a SharePoint page’s ribbon menu

Photo by Drew Rae from Pexels

I know I’m blogging a lot about CSS changes lately, and it’s not normally something I recommend. But for a very specific project of mine, I’ve been doing a lot of this and am sharing a few tips along the way in case they help others needing to accomplish something similar.

Hide the Browse and Edit buttons/tabs

Click to enlarge

In this post, I’ll share how to hide the Browse and Edit tabs from the ribbon menu of a SharePoint page. This only applies to classic experience pages. To hide these tabs/buttons, add the following CSS inside a <style> tag to the page(s) on which you wish to remove these options.

.ms-cui-tt a[Title='Browse'],.ms-cui-tt a[Title='Edit']{
display:none;
}

If you’re unsure how to add CSS to your page, this post details the steps with a different script. Just use the script above inside <style> tags instead.

You can also hide other tabs like Page, Files, Library, etc. by adding a comma right before the opening brace ({) and then pasting another .ms-cui-tt a[Title=’Page’] (substituting the tab name of course). This only works for some, but not all tabs.

Hide the Share, Follow, and Focus/Full Screen buttons

You may also wish to hide the three buttons on the right side of the ribbon seen here:

Click to enlarge

Similar to above, we’ll just set the #RibbonContainer-TabRowRight ID to not display. This one has to have !important added inside the semi-colon for it to override competing code and take affect as expected.

#RibbonContainer-TabRowRight{
display:none!important;
}

Style embedded html iframe and border so it doesn’t look sunk on the page

Photo by Zukiman Mohamad from Pexels

If left unstyled, your embedded iframe content when working with html pages appears inside “sunken” boxes/frames (browser and context-dependent, of course). I don’t find this look to be very appealing, so I typically adjust the iframe’s properties a bit in the html to give it a little less sink and a little more pop. I add specific width and height values to be exact about where I’m placing it and what it contains, and I use box-shadow instead of border which gives it that “lift” off the page.

Consider the following script just a starting place, then get creative with your own content and design. You’ll want your embedded content to “fit in” with the rest of its page’s contents so try to be consistent if you have other boxed elements/containers on the page (Tip: Use F12 and element selection to see the style properties of other parts of your page).

<iframe src="https://sharepoint.contoso.com/SitePages/MyLinks.aspx" border="0" frameborder="0" style="border-style:none;box-shadow:0px 0px 2px 2px rgba(0,0,0,0.2);width:262.5px;height:250px;" cellspacing="0"></iframe>

P.S. I’m sure I could write this prettier, but it works. For instance, you could reference the iframe in your CSS rather than hard-coding it in the html body.

Make full-width SharePoint hyperlink column clickable beyond just the link text

Photo by Pixabay from Pexels

This is such an obscure topic, but maybe it will help somebody curious out there. I recently had a request to alter a classic experience list with a single hyperlink column so that users could click in the white space of a cell and it takes them to that cell’s hyperlink value as if they’d actually clicked the link.

To illustrate what I mean, notice how the arrow pointer changes to a hand cursor like the whole cell is clickable. And when white (blue) space of the Google link is clicked, it takes us to Google anyway:

Click to enlarge

This was done with the tiniest bit of CSS added to the page inside a <style> tag. Note that this will affect all links in tables on the page to which it’s applied. So if you have more than one table on the page, this could cause issues. But in my case I just had the single-column list I was working with and this sufficed.

td a {
    display:inline-flex;
    width:100%;
}

Good luck!

Solution: SharePoint Designer email action’s To: line has a valid email address, but is removed and doesn’t send when triggered

Photo by Snapwire from Pexels

If you’ve created a workflow in SharePoint Designer and an email action appears to be configured correctly, but emails aren’t being sent to some individuals in the To: line, you may need to turn the email being used into a workflow variable and use that instead of direct addition to the To: line of the email step.

This often happens for group email inboxes or external recipients that aren’t just a “normal user.” If there is a mix of recipients, some may receive the message but the troublesome addresses don’t even appear in the To: line, as if they’re removed before sending.

Note: If you’re sending to external recipients specifically and this post doesn’t solve your problem, check out my other post for additional help: Sending emails via SharePoint Designer workflow to external recipients using Gmail, Yahoo, Hotmail, etc. addresses

To “variablize” an email (this is using a SP 2010 platform workflow type):

1. Set a new workflow variable of type string to the email address(es) that aren’t receiving emails as expected.

Click to enlarge
Click to enlarge
Click to enlarge

2. Now in your email settings, use the “Workflow Lookup for a User” option and select your new variable from “Workflow Variables and Parameters” data source.

Click to enlarge
Click to enlarge
Click to enlarge

3. Publish the changes to your workflow and test.

SharePoint conditional column formatting with JSON: Beginner, intermediate, and advanced background colors example

I borrowed from Microsoft’s documentation on conditional column formatting recently to modify a modern experience list in SharePoint 2019. This also works for SharePoint Online/O365, but will not work in classic experiences (or pre-2019 server versions). I modified Microsoft’s example on conditional background colors for a numeric range and created a similar conditional column formatting result for text values.

In this example, I have a list for upcoming training opportunities. There’s a column named “Level” which is a choice field of either Beginner, Intermediate, or Advanced. The JSON code at the bottom of this post changes the column’s background color value to green, yellow, or red respectively based on the level selection. Here’s a demonstration of the result:

Click to enlarge.

You could modify this code to suit your own column’s values/options, then paste it into the Column Formatting section of that column’s settings (List settings > Select column from Columns section). Do not change @currentField in the JSON code – that’s just a reference to whichever column you add it to and doesn’t need to be your column’s name.

Click to enlarge
{  
  "elmType": "div",  
  "txtContent": "@currentField",  
  "style": {  
    "color": "#fff",  
    "padding-left": "14px",  
    "background-color": {  
      "operator": "?",  
      "operands": [  
        {  
          "operator": "==",  
          "operands": [  
            "@currentField",  
            "Beginner"  
          ]  
        },  
        "#2ECC71",  
        {  
          "operator": "?",  
          "operands": [  
            {  
              "operator": "==",  
              "operands": [  
                "@currentField",  
                "Advanced"  
              ]  
            },  
            "#E74C3C",  
            {  
              "operator": "?",  
              "operands": [  
                {  
                  "operator": "==",  
                  "operands": [  
                    "@currentField",  
                    "Intermediate"  
                  ]  
                },  
                "#F1C40F",""
              ]  
            }  
          ]  
        }  
      ]  
    }  
  }  
}

Auto-approval of Microsoft Teams Shifts requests using Power Automate

Today I happily stumbled across a collection of Power Automate templates for auto-approval of different types of Microsoft Teams Shifts requests, such as time off requests, open shift requests, and swap requests.

Not familiar with Shifts? Check out my write-up.

The ability to auto-approve removes the current reliance on a Team owner to approve requests. In less formal Teams, this would be an excellent improvement to speed up the process and give autonomy to your team members.

While most of the templates’ triggers are set to use “Recurrence” (regularly reviewing requests and approving on the hour), you can also create your own flow using Shifts itself as a trigger instead.

Note: In high-activity Teams, using Recurrence as the trigger might cut down the number of runs/flows you use if that’s a consideration for you. Using Shifts as the trigger as seen below will run every time a request is made, but provides a faster response to your users.

Click to enlarge.

The templates for Power Automate auto-approval of Shifts requests range from simple flows to more complex flows. Check them out below:

  1. Auto Approve Offer Shift Requests
  2. Auto Approve Open Shift Requests
  3. Auto Approve Swap Shifts Requests and Send Email Notification
  4. Auto Convert Shift to Open Shift
  5. Share My Shifts as iCalendar Feed
Auto Approve Offer Shift Request
Image taken from Auto Approve Swap Shifts Requests and Send Email Notification template example. Click to enlarge.

Delete random blank Excel cells and shift remaining cells left to fill the gaps

Photo by Andrea Albanese from Pexels

I love learning new things. Today I was using a CSV export of data in Excel and was just using Excel to reassemble the data. At one point it resembled something like:

This is, of course, after some manipulation. Basically I removed the parts of a URL column expanded by delimiter (“/”) I didn’t want. This left awkward gaps and all I wanted was to quickly delete the gaps and shift contents of remaining cells to the left to sort of “reconstruct” each row without gaps. Since they didn’t line up in neat columns, I needed a different method.

I found a great article that helped. To summarize the steps:

  1. Select the range for which you’ll delete blank cells and shift data left.
  2. Press Ctrl+G.
  3. Click Special… (lower left of dialog)
  4. Choose the Blanks radio button
  5. Click OK.
  6. All blank cells in the selected range remain highlighted. Now right-click any of the selected blank cells.
  7. Choose Delete.
  8. Select Shift cells left.
  9. Click OK.

Here’s an animated GIF showing the process on my example data:

Click to enlarge

Export a report of all SharePoint lists, libraries, discussion boards, calendars, and more from all site collections with PowerShell

Photo by Tiger Lily from Pexels

I wanted to get an idea of how many people were using discussion boards in my SharePoint Server environment and in what sites. I modified a script I found to create the sort of inventory list I needed and ended with a script that:

  • Provides a list within PowerShell of each URL, site name, and list name found matching a specific list type.
  • Provides a total count and save location confirmation at the end.
  • Exports a CSV file of the details to a specified location.

Find the Template ID for the list you’re searching for

List template ID options are as follows, taken from this Docs article. You’ll need the Template ID of the type of list you wish to search in your SharePoint environment.

List template typeTemplate IDBase typeDescription
Custom List1000A basic list that can be adapted for multiple purposes.
Document Library1011Contains a list of documents and other files.
Survey1024Fields (2) on a survey list represent questions that are asked of survey participants. Items in a list represent a set of responses to a survey.
Links1030Contains a list of hyperlinks and their descriptions.
Announcements1040Contains a set of simple announcements.
Contacts1050Contains a list of contacts used for tracking people in a site (2).
Calendar1060Contains a list of single and recurring events. An events list has special views for displaying events on a calendar.
Tasks1070Contains a list of items that represent finished and pending work items.
Discussion Board1080Contains discussions entries and their replies.
Picture Library1091Contains a library adapted for storing and viewing digital pictures.
DataSources1101Contains data connection description files.
Form Library1151Contains XML documents. An XML form library can also contain templates for displaying and editing XML files through forms, as well as rules for specifying how XML data is converted to and from list items.
No Code Workflows1171Contains additional workflow definitions that describe new processes that can be used in lists. These workflow definitions do not contain advanced code-based extensions.
Custom Workflow Process1180Contains a list used to support custom workflow process actions.
Wiki Page Library1191Contains a set of editable Web pages.
CustomGrid1200Contains a set of list items with a grid-editing view.
No Code Public Workflows1221A gallery for storing workflow definitions that do not contain advanced code-based extensions.
Workflow History1400Contains a set of history items for instances of workflows.
Project Tasks1500Contains a list of tasks with specialized views of task data in the form of Gantt chart.
Public Workflows External List6000An external list for viewing the data of an external content type.
Issues Tracking11005Contains a list of items to track issues.
Table of list template IDs taken from https://docs.microsoft.com/en-us/openspecs/sharepoint_protocols/ms-wssts/8bf797af-288c-4a1d-a14b-cf5394e636cf.

Modify the PowerShell script to suit your needs

Once you have the list template ID you wish to query from the table above, modify the PowerShell script found below as follows:

  1. Replace the $ListTemplateId variable value with your desired template ID.
  2. Replace the -WebApplication parameter’s URL value with your own SharePoint web app address.
  3. Replace the $saveCSVLocation value inside the double-quotes with the path to where you’d like the export to be written.

Get all SharePoint list types in one report

Want it all? You could modify the script by replacing -eq $ListTemplateId on line 15 with -gt 0. Then replace line 21 with:

@{Site=$web.Title;ListName=$list.Title;Type=$list.BaseTemplate;URL=($web.Url + "/" + $i.DefaultView.Url)}) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }

And replace line 25 with:

write-Output ($web.Title + "," + $list.Title + "," + $list.BaseTemplate + "," + $web.Url + "/" + $i.DefaultView.Url) | Out-File $SaveLocationFinal -Append

Now your report will include all list types, and an added column to specify that list type. Note that this will take a while to run in larger environments.

You could also modify the script to only display in PowerShell (delete lines 23-25 and 31-33) or only export to CSV (delete lines 19-22 and 31-33) but I wanted both outputs for my purposes.

Idea: Take it further with Power BI

Take this to the next level by automating the PowerShell script to run on a schedule exporting results to a folder Power BI reads on an automatic refresh. This is an easy way to get a hands-off dashboard of SharePoint usage by list type.

Free Microsoft 365 training for beginner level SharePoint, Microsoft Teams, Power Apps, Power Automate, OneNote, and Microsoft Project

Mark Jones of Collab365 shared the following LinkedIn post recently with free training links for beginning SharePoint, Microsoft Teams, Power Apps, Power Automate, OneNote, and Microsoft Project topics. No signup, no emails, just free training with no strings attached. Be sure to take advantage of this amazing opportunity.

Also, be sure to register for #GlobalCon4 for FREE. This time, they’re introducing a series of 15-minute turbo sessions on several topics you won’t want to miss.