-
-
Save guillaumemeyer/fe4ed1b818c5d99eabff1c792a366f71 to your computer and use it in GitHub Desktop.
// **************************************************************************************************************************** | |
// Abstract: | |
// This script is just a quick hack to export the owners and members of a team as a CSV file without administrator permissions. | |
// | |
// Usage: | |
// 1. Open your team | |
// 2. Select "Manage team" from its menu | |
// 3. Select the "Members" tab | |
// 4. Expand the "Owners" and "Members and guests" sections | |
// 5. Make sure to scroll down to the end of the owners and members lists to include all of them in your export (As the members are loaded on demand) | |
// 6. Open your browser console | |
// 7. Copy and paste all the content of this script to the console and type "Enter" | |
// 8. The CSV file download should start automatically | |
// | |
// ToDo: | |
// - Parse tags to include them in the export | |
// **************************************************************************************************************************** | |
$(function() { | |
// ************** | |
// Initialization | |
// ************** | |
const csvFileName = 'team-membership-roster-export.csv' | |
const csvDelimiter = ',' | |
const csvHeader = 'Display Name' + csvDelimiter + 'Title' + csvDelimiter + 'Location' + csvDelimiter + 'Role' + csvDelimiter + 'UPN' + '\r\n' // CSV header row | |
let csvContent = csvHeader // Initialize CSV content | |
const rosterLength = $('.td-member-display-name').length // Number of visible members | |
// Check if we're an owner of the team | |
let roleSelector = '.td-member-role' // Consider we're not an owner by default | |
if ($('.td-member-editable-role').length > 0) { | |
roleSelector = '.td-member-editable-role' // Override if we're an owner | |
} | |
// ************************ | |
// Iterate over each member | |
// ************************ | |
for (let index = 0; index < rosterLength; index++) { | |
// Extract the display name, title, location and role | |
const displayName = $('.td-member-display-name').eq(index).text() | |
const title = $('.td-member-title').eq(index).text() | |
const location = $('.td-member-location').eq(index).text() | |
const role = $(roleSelector).eq(index).text() | |
const upn = $('.td-member-photo img').eq(index).attr('upn') | |
// Append to the CSV content | |
const csvRow = displayName + csvDelimiter + title + csvDelimiter + location + csvDelimiter + role + csvDelimiter + upn + '\r\n' | |
csvContent += csvRow | |
} | |
// Debug the export to console | |
console.info(rosterLength + ' members exported:') | |
console.info(csvContent) | |
// ********************************************************** | |
// Dynamically generates a CSV file and triggers its download | |
// ********************************************************** | |
// Create a dynamic "a" tag | |
var element = document.createElement('a') | |
// Set href link with content | |
element.setAttribute( | |
'href', | |
'data:application/json;charset=utf-8,' + encodeURIComponent(csvContent) | |
) | |
// Set downloaded file name | |
element.setAttribute('download', csvFileName) | |
// Hide the elemement and add it to the page | |
element.style.display = 'none' | |
document.body.appendChild(element) | |
// Launch download | |
element.click() | |
// Remove element | |
document.body.removeChild(element) | |
}) |
I have slightly updated code here with a couple of enhancements. I am still able to export full membership for teams I'm in (owner or just a member) testing up to a couple hundred members. I am having problems getting a full export for a larger team (1200+ members) that I used to be able to export.
I believe we are starting to see changes coming to Teams web, as Microsoft has the new Teams web client now available (depending on how your organization is rolling out new Teams).
In Classic Teams, the Javascript code has clear methods to decern the appropriate sections of the webpage to grab and export. For example, the code keys on the CLASS attribute to find the member's display name against a DIV tag like below:
<div class="td-member-display-name">
<span>
James T. Kirk
</span>
</div>
In new Teams web client, the code would be sifting through this new HTML code:
<div class="fui-Flex ___dkbdks0 f1bxpd7w">
<div class="___87nhvx0 fau6ura f3052tw lpcCommonWeb-hoverTarget container-161">
<span role="img" id="avatar-12580" class="fui-Avatar r81b29z ___1ywy82q f1tlnv9o f13ar0e0 fid048z">
<div role="img" id="presence-pill-8:orgid:e2d2f6e0" class="fui-PresenceBadge r832ydo fui-Avatar__badge ___1i6sv73 f11d4kpn f1euv43f f1yab3r1 f1e31b4d">
</div>
</span>
</div>
<span class="fui-StyledText ___1a76sp3 fz5stix f1p9o1ba f1sil6mw f1cmbuwj f1g0x7ka fhxju0i f1qch9an frdkuqy" aria-label="James T. Kirk (Guest)">James T. Kirk (Guest)</span>
</div>
</div>
In the new Teams web client code above, I think it gets harder to drill into the proper attribute to retrieve the data we want.
I'm only able to export the owners in Edge, but this still works in Chrome :)
For me, it's also only exporting the administrators, not the members :-(
I have slightly updated code here with a couple of enhancements. I am still able to export full membership for teams I'm in (owner or just a member) testing up to a couple hundred members. I am having problems getting a full export for a larger team (1200+ members) that I used to be able to export.
I believe we are starting to see changes coming to Teams web, as Microsoft has the new Teams web client now available (depending on how your organization is rolling out new Teams).
In Classic Teams, the Javascript code has clear methods to decern the appropriate sections of the webpage to grab and export. For example, the code keys on the CLASS attribute to find the member's display name against a DIV tag like below:
<div class="td-member-display-name"> <span> James T. Kirk </span> </div>
In new Teams web client, the code would be sifting through this new HTML code:
<div class="fui-Flex ___dkbdks0 f1bxpd7w"> <div class="___87nhvx0 fau6ura f3052tw lpcCommonWeb-hoverTarget container-161"> <span role="img" id="avatar-12580" class="fui-Avatar r81b29z ___1ywy82q f1tlnv9o f13ar0e0 fid048z"> <div role="img" id="presence-pill-8:orgid:e2d2f6e0" class="fui-PresenceBadge r832ydo fui-Avatar__badge ___1i6sv73 f11d4kpn f1euv43f f1yab3r1 f1e31b4d"> </div> </span> </div> <span class="fui-StyledText ___1a76sp3 fz5stix f1p9o1ba f1sil6mw f1cmbuwj f1g0x7ka fhxju0i f1qch9an frdkuqy" aria-label="James T. Kirk (Guest)">James T. Kirk (Guest)</span> </div> </div>
In the new Teams web client code above, I think it gets harder to drill into the proper attribute to retrieve the data we want.
Hey @joegasper, great insight. Do you think there is a way to write the code so that it tries to pick up every time is says "member"? (see image)
Hey, I just copy paste it directly from teams in excel (New Teams). Select 'Name' under Manage channels>Members&guest till the last member (four columns, not using tags). Next I paste it in column B in excel. In column A I indicate if it is a Name, Title, Location or Role before the record.
This VBA script will make a decent table as from column D to G:
Sub ListMaker()
Dim lastRow As Long
Dim i As Long
Dim destRow As Long
Range("D2:G389").Select
Selection.ClearContents
Range("C10").Select
' Find the last row with data in column A
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
' Initialize the destination row
destRow = 2
' Loop through each row
For i = 2 To lastRow
' Check the value in column A and transfer the corresponding value to the appropriate column
Select Case UCase(Cells(i, 1).value)
Case "NAME"
Cells(destRow, 4).value = Cells(i, 2).value
Case "TITLE"
Cells(destRow, 5).value = Cells(i, 2).value
Case "LOCATION"
Cells(destRow, 6).value = Cells(i, 2).value
Case "ROLE"
Cells(destRow, 7).value = Cells(i, 2).value
' Add more cases as needed
End Select
' Move to the next destination row after processing each category
If UCase(Cells(i, 1).value) = "ROLE" Then
destRow = destRow + 1
End If
Next i
Columns("B:B").Select
Selection.ClearContents
Range("B10").Select
End Sub
Does this work for https://teams.microsoft.com/v2/ because I don't get a CSV file.
Does this work for https://teams.microsoft.com/v2/ because I don't get a CSV file.
I've been unable to get this to function in "New Teams" myself.
This script is not easily maintainable due to its reliance on unpredictable MS UI updates.
I'm currently investigating a completely different solution to achieve the same result.
Stay tuned
is there a latest script to download members and owners from teams? can anyone help?
I've found that if you're on 365, you can get a list now with functions available in https://portal.azure.com/#home, even if you're not an admin.
Same issue here. Only the administrators are currently being exported.
I hope someone can resolve this issue, since this script has been very handy for us so far