Did you know … you can mark a Teams post unread?

One of the first settings I tweak when I get a new computer – before setting up my printers, grabbing FireFox from the Software Center, or setting up Putty sessions to our hosts is to STOP Microsoft Outlook from marking a message read every time I click on it. Yes, you can add a delay – mark it read if the message has been displayed for 10 seconds. But if I’ve really read a message, I either reply to it (which marks it as read) or delete it. On the few occasions where I want to stash the message without replying, I can mark it read myself!

Teams is different than Outlook … I cannot just delete someone’s post because I’ve read it.

The channel is bolded again to indicate there are unread posts.

And the ‘last read’ marker is moved prior to the message.

Currently (13 February 2019), marking a post unread in a channel discussion does not make it show up when you filter your activity feed for unread messages. If you mark the message as unread within the Activity Feed, though, the item will appear in the “Unread Messages” filtered view.


Did you know … you can link SharePoint Lists?

There is a lot of nicely self-contained data – I track usage and membership stats to track adoption and predict future capacity needs, and a single list contains everything I need to know. But sometimes it’s not possible to keep complete records in a single table – two different processes update the information, and there is a need to isolate access to the more confidential information. As an example, I have a process that updates employee e-mail addresses in PeopleSoft. I don’t have any reason to read employee evaluations or payroll information. Even where it is possible, it can be inefficient. Data duplication can be eliminated by keeping the information in separate tables.

In a relational database, this is called normalization. Instead of maintaining a single table with orders where the customer’s name, address, contact person, phone number, etc are stored on every single order … you create a table with order-specific data (what did they order, how many, how much did it cost) and include a single column for customer number. Another table has the customer number and their contact information. If the customer moves their office, you don’t have to go through and update hundreds of orders – just go into the customer table and update their record. All orders will use the new address. To retrieve an amalgamated record, use JOIN in the query (or create a view using a JOIN query).

You can do something similar with SharePoint lists. As an example, I will use lists with customer contact information and a list with orders. First, we need a list with customer information. Add an index for the column that will be used to find the customer record – in this case, it is CustomerID. Click on “Indexed columns”.

Click “Create a new index”

Select the column to index and click “Create”

You now have an index – something to speed up searching your list for CustomerID.

We’ll also need a list with customer orders. Create all of the columns that aren’t populated by lookup *or* the field on which the lookup occurs. Then Add lookup column using “Add Column” and selecting “More”

Name it & select “lookup” as the data type.

Some of the column settings will depend on your particular use case. Requiring data: are there going to be orders where the site isn’t known yet? Should the values be unique (in this case, no, since I hope my customers return and place a second order!).

From the “Get information from” drop-down, select the table that stores the associated information. The page will reload; from the “In this column” drop-down select the value you want to store in this lookup column – what information is being cross-referenced? Here, it’s the customer ID number. Then check all of the columns you want to populate based on the lookup field. Here, I’m pulling in the customer’s name and mailing address details.

I specifically configure this table’s records not to be deleted if the record gets pulled from the lookup table. Again, this will depend on your use case. Hit OK to create the column.

When creating a new record, you won’t even see the columns we’ve checked above – there will be a drop-down where you can select the data on which the lists are correlated.

When you save the record, the remaining columns display information from the customer information table.

What if you don’t want a drop-down with ten thousand customer numbers? (A perfectly reasonable request – I’ve loaded a few thousand customers in my list and there’s no way I want to scroll through all of those numbers and hope to get the right one).

You can turn the drop-down list into a searchable drop-down by using PowerApps to customize the input form. Click the not-quite-a-hamburger menu between the list name and “List” and select “Settings”

On the settings page, select “Form settings”

Click the “Customize in PowerApps” hyperlink.

Wait a minute as the new app is built.

In the right-hand tool bar, find the “Fields” section and click “Edit”.

On the menu that flies out to the left, click on “Add fields”

Select the fields for the input form and click “Add”

The drop-down box in PowerApps is searchable

In the ribbon bar, select “File”

Click “Save” to save the app

When the app has saved, click “Publish to SharePoint”

You will see a warning that publishing the app to SharePoint makes it visible to anyone who uses your list. Click to continue publishing the app to SharePoint.

Verify that the app is published successfully.

Click “Back to SharePoint” to return to your list.

In the list settings, verify that the custom form is selected for your list.

On the data entry card, you will see that the drop-down is now searchable.

When you type some text into the drop-down, you will see a filtered list of options.

** This works provided the list against which the lookup is performed (in this example, my customer list) contains 5,000 or fewer records. If you see an error like this, then you’ve exceeded 5,000 records in the lookup table.

There are a few options – the generally recommendation from Microsoft is to break the list into multiple lists. This may mean breaking the data into different, unrelated lists. Or it may mean establishing a parent/child list relationship (e.g. a customer list that has multiple entries per customer reflecting their various offices could be a parent list of customers and a list for each customer reflecting their sites). You may be able to use a view, filtered to a subset of records, for data entry. Writing a custom web input form and using the SharePoint REST API to read and write data would allow you to populate the searchable drop-down with data retrieved from the lookup target (in this case my customer table) – as the column is indexed, the threshold should not be exceeded as you search.


In an emergency … build a wall??

Efficacy and waste of money aside, the best thing would have been to give him the cash. If Congress can pass one-off legislation on end of life care for a single individual, they could have one-off’d letting the GoFundMe buy a wall. And then the dude could have absolutely failed at building a wall because, well, he runs the government *just like* he runs his awful businesses. Hell, he *builds* the wall and we still have people overstaying visas, meth cooks out in Illinois, murders, and traffic accidents — bad PR for the wall, that.

This is the martyr path — no wall means no stats to show how ineffective it was, he can keep crowing about how amazing he is at building all sorts of things, we’ll be treated to endless bitching about how no other president has had to deal with this judicial intrusion into their agenda, the case becomes a rallying point for the base and yet another justification for activist judges. I was shocked he didn’t go national emergency before the shutdown — strategically, it really seems like the best solution (a priori assumption: everyone from the administration knows the wall is a heap of theater thus knows theater with no tangible artifacts is an improvement)

Did you know … your Team can have 5,000 members?

Microsoft updated the Microsoft Teams Limits and Specifications documentation, an Teams can now have 5,000 members. That’s a LOT of people! Are there special considerations when managing a large Teams space? Yes!

Even in a smaller team, it is a good idea to document the purpose of the Teams space and how it should be used. Is there a channel into which members are encouraged to post interesting information they happen across even if said information is not directly work related? Can members create new channels; and, if not, how are new channels requested? When managing a large Team, it is vital that everyone understand the purpose for each channel and what types of discussion are appropriate.

Because you cannot currently pin a post to the top of a channel, I have used the General channel’s Wiki tab to convey this information. You can rename the Wiki tab – a good idea if it will be more than a blank page! Click the drop-down by “Wiki” and select “Rename”.

Type a new name and click “Save”.

Update the Wiki page with information about your Team.

The first real problem in creating a large team is picking 1,739 names and adding them to your team. Instead of manually adding individual members, you can generate a code that can be used to join your team. This code can be e-mailed to those who should join – or to managers for distribution to their staff. Click the not-quite-a-hamburger menu next to your Team name and select “Manage Team”

Click on the “Settings” tab, expand the “Team code” section, and copy the code.

Click on the “Members” tab – that “Search for members” dialogue is very useful if you want to remove a specific member from a very large team.

There are other settings that can reduce chaos in large Teams spaces. Click the “Settings” tab. Expand the “Member permissions” section. If thousands of people can create channels, you can quickly reach the 200-channel limit in a Teams space. By restricting channel creation and deletion to Team owners, you can exert more control over the Teams space design. You can even prevent non-owners from posting to the General channel. I do not allow members to modify tabs or connectors – again, controlling what the space looks like and avoiding accidental deletions.

It is beneficial to allow Owners to delete all messages – if a post is inappropriate or contains information that should not be shared with the large group, it can be quickly removed.

Scroll down and expand the “@mentions” section – since at-mentions generate notifications to a huge number of people, you may not want to allow members to at-mention the team or channel.

You may want to restrict “fun stuff” as well – a few gifs or memes can be funny, eight hundred … not so much 😊


Did you know … you can schedule a meeting from a Teams chat?

Clicking around in a UI (or even using shortcut keys to navigate elsewhere) can make you lose focus – but it would be overwhelming to see your calendar, all channel activity, shared files, calendar, and Planner overview in the same view. Fortunately, there are shortcuts in Teams that allow you to perform quick actions without leaving your current screen.

There are discussions that are well suited to IM-like interfaces – I frequently bring up a side-channel chat for conference calls to run ideas by my group before announcing it to others or to get clarification about a topic without interrupting the flow of discussion. When participants span time zones, asynchronous communication allows everyone to participate in the discussion. But there are times when it’s just easier to talk. If everyone is available, you can launch an audio or video meeting right from the upper right-hand corner of the chat.

That doesn’t work if everyone’s not available to talk. While you can schedule a meeting in the Meetings panel, that means leaving your current conversation. Fortunately, you can also schedule a meeting from the chat pane. Under the new message box, click the little calendar icon.

And schedule a meeting – attendees are pre-populated with chat participants, but you can add and remove participants as needed.


Did you know … you can add a subject to your Channel conversations?

It can be time consuming to scan through channel conversation and find posts that are really relevant to you – unlike e-mails that have conveniently scan-able subjects, Teams can seem like a deluge of threads, and you’ve got to read through each one to see if it’s something important to you or not.

To some extent, breaking topics out into different channels and Teams helps, but few are deeply involved in every single aspect of a discussion. And personnel matters discussed in a group’s Teams space often only impact some people – announcements about the Education Assistance policy, the deadline for the smoking cessation program, or weather information for a specific office may be really important to you or they may be something you could have ignored if you hadn’t needed to read the first sentence or two before disqualifying yourself.

But Teams threads do have subjects – it’s just really easy to start a thread without one (unlike e-mail where it’s glaringly obvious that your subject is missing). To add a subject to your thread, either hit Ctrl-Shift-x or click the ‘Format’ button to expand the rich text editor.

Now there’s a thread subject – type a quick summary just like you would have in an e-mail message and type your thread content in the ‘Start a new conversation …’ section.

When you post your message, your subject will appear in larger, bolded text. This allows channel members to quickly scan through threads and decide if they need to read them or not.

Subjects are even highlighted in search results – making it easier to find your thread in searches (and scanning through a channel when not using search).


Did you know … you can @mention your Team without typing the whole Team name?

If you want to bring the entire team’s attention to a post without taking half a second to think about which Team you are actually using, you can use @team instead. @team will resolve to whatever Team into which the message is posted. These shortcuts are only available in Teams channel conversations – typing @team in a private chat won’t do anything.

There’s a shortcut for the current channel too — @channel

The message text is the same using @team and @channel or typing the actual team and channel name.


Did you know … you can send a quick Teams IM without losing focus on what you are doing?

There are times when a question for a specific individual can be asked in the channel conversation by @mentioning the individual. But sometimes the question isn’t for general consumption … and sometimes I a message reminds me of something completely different that I need to tell someone. But switching to ‘Chat’ to send a message and then finding my way back to the channel conversation is time consuming. Did you know you can send a private message from the search bar?

Hit Ctrl+e or click in the search/command box along the top of the Teams window.

Begin typing an @Mention – either select the proper individual or type enough of the name that there’s only one …

Now you can send a message to the selected person right from the search bar.

Type your message – this is a quick text message, there isn’t typographical emphasis, colors, cute pictures – markdown doesn’t even render. But I can send a quick message without losing my place within the Channel conversation! Hit send (enter or the little purple circle at the end of the dialog box).

You’ll see a confirmation that your message was sent (and you can view the message in your persistent chats). And you can get right back to what you were doing 😊


List locally installed Python modules

I’ve been helping someone else get an Azure bot running on their system … which involves a lot of “what do I have that you don’t” … for which listing locally installed python modules is incredibly helpful.

python -c “import pkg_resources; print([(d.project_name, d.version) for d in pkg_resources.working_set])”


[lisa@cent6 ljr]# python -c “import pkg_resources; print([(d.project_name, d.version) for d in pkg_resources.working_set])”
[(‘scipy’, ‘1.2.0’), (‘scikit-learn’, ‘0.20.2’), (‘PyYAML’, ‘3.13’), (‘PyMySQL’, ‘0.9.3’), (‘pycares’, ‘2.4.0’), (‘numpy’, ‘1.16.0’), (‘multidict’, ‘4.5.2’), (‘Cython’, ‘0.29.4’), (‘coverage’, ‘4.5.2’), (‘aiohttp’, ‘3.0.9’), (‘yarl’, ‘1.3.0’), (‘wrapt’, ‘1.11.1’), (‘vcrpy’, ‘2.0.1’), (‘typing’, ‘3.6.6’), (‘sklearn’, ‘0.0’), (‘singledispatch’, ‘’), (‘sharepy’, ‘1.3.0’), (‘requests-toolbelt’, ‘0.9.1’), (‘requests-oauthlib’, ‘1.2.0’), (‘pytest’, ‘4.1.1’), (‘pytest-cov’, ‘2.6.1’), (‘pytest-asyncio’, ‘0.10.0’), (‘PyJWT’, ‘1.7.1’), (‘py’, ‘1.7.0’), (‘pluggy’, ‘0.8.1’), (‘oauthlib’, ‘3.0.1’), (‘nltk’, ‘3.4’), (‘msrest’, ‘0.4.29’), (‘more-itertools’, ‘5.0.0’), (‘isodate’, ‘0.6.0’), (‘ConfigArgParse’, ‘0.14.0’), (‘certifi’, ‘2018.11.29’), (‘botframework-connector’, ‘4.0.0a6’), (‘botbuilder-schema’, ‘4.0.0a6’), (‘botbuilder-azure’, ‘4.0.0a6’), (‘azure-devtools’, ‘1.1.1’), (‘azure-cosmos’, ‘3.0.0’), (‘attrs’, ‘18.2.0’), (‘atomicwrites’, ‘1.2.1’), (‘async-timeout’, ‘2.0.1’), (‘aiodns’, ‘1.2.0’), (‘botbuilder-core’, ‘4.0.0a6’), (‘systemd-python’, ‘234’), (‘smartcols’, ‘0.3.0’), (‘setools’, ‘4.1.1’), (‘rpm’, ‘’), (‘gpg’, ‘1.11.1’), (‘cryptography’, ‘2.3’), (‘cffi’, ‘1.11.5’), (‘urllib3’, ‘1.24.1’), (‘SSSDConfig’, ‘2.0.0’), (‘slip’, ‘0.6.4’), (‘slip.dbus’, ‘0.6.4’), (‘six’, ‘1.11.0’), (‘setuptools’, ‘40.4.3’), (‘sepolicy’, ‘1.1’), (‘requests’, ‘2.20.0’), (‘PySocks’, ‘1.6.8’), (‘pyparsing’, ‘2.2.0’), (‘pyOpenSSL’, ‘18.0.0’), (‘pykickstart’, ‘3.16’), (‘PyGObject’, ‘3.30.4’), (‘pycparser’, ‘2.14’), (‘ply’, ‘3.9’), (‘pip’, ‘18.1’), (‘ordered-set’, ‘2.0.2’), (‘isc’, ‘2.0’), (‘IPy’, ‘0.81’), (‘iotop’, ‘0.6’), (‘iniparse’, ‘0.4’), (‘idna’, ‘2.7’), (‘distro’, ‘1.3.0’), (‘decorator’, ‘4.3.0’), (‘chardet’, ‘3.0.4’), (‘asn1crypto’, ‘0.24.0’)]

Did you know … you can bookmark Teams posts for quick access?

There are a few posts to which I frequently refer – support contacts for a product, time reporting codes to use for our projects, etc. These posts aren’t updated frequently, so looking for them takes some scrolling. Searching for the post helps, but I still find myself scrolling through a dozen results.

You can save a post for later – essentially add a bookmark to the post – by clicking the little ribbon in the upper right-hand corner of the post.

To access saved posts, click on your avatar in the upper right-hand corner of Teams and select “Saved”.

Or, if you prefer to keep your hands on the keyboard, use CTRL + E to move to the command bar and type /saved

Either method brings you to the same place – your saved posts.