Sharepoint
PowerApps Functions
On 30/09/2022
PowerApps functions
Parse text to number
Filter('Workflow Tasks'; ID = Value(txtId.Text))
Add datas (listItem)
Patch(NewVoie;Defaults(NewVoie);{Num_x00e9_rovoie:"0"&LookUp(NewVoie;ID=1).Num_x00e9_rovoie}))
Update context, and forms datas
SubmitForm(FormBeneficiaires);;ResetForm(FormBeneficiaires);; NewForm(FormBeneficiaires);; UpdateContext({showPopup:false});
If(IsBlankOrError(SubmitForm(Form1)), Set(saveStatus, "An error occured" & Form1.Error), Set(saveStatus, "Operation succeded"))
Navigate to another form
Navigate(Page_infos_enregistrements)
Get query string parameter and set a variable
Set(InitiativeId; Param("ID"))

Get a field from your datasource by ID
First(Filter(Initiatives; ID=1)).Nom
And Or Not
Or(And(Radio1.Selected.Value=4; !IsBlank(txtComment.Text));Radio1.Selected.Value<4)
Update Lookup Field
Patch(
ResultatAnalyses;
First(//here item to update
Filter(
ResultatAnalyses;
Affaire.Id = currentAffaire.ID And Analyse.Id = ThisItem.ID
)
);
{
Title: "notused";
Commentaires: txtGalComment.Text;
Gravite: Rating1.Value;
Affaire: {//lookup field name
Id: currentAffaire.ID;//id of lookup
Value: LookUp(
Affaires;//list who contains lookup value
ID = currentAffaire.ID;//id of lookup
currentAffaire.Title//title of lookup value
)
}
}
)
Patch Choice
TypeIntervention: {Value: dtvTypeIntervention.Selected.Value}
Execute automate with json
'My workflow'.Run(
JSON(
{
SolutionId: selectedSolution.ID,
ImageContent: UploadedImage14.Image
},
JSONFormat.IncludeBinaryData
)
);
Reg ex to get cleaned string
Clear(AttachmentsCollection);
ForAll(
RenameColumns(DataCardValue91.Attachments, "Name", "Name1"),
Collect(
AttachmentsCollection,
Name1
)
);Set(Title1, First(AttachmentsCollection).Value);Set(FileName1, Concat( Split(First(AttachmentsCollection).Value, "" ), If( IsMatch(Result, "([^A-Za-z0-9\.\-])" ), "",Result ) ))
Save Form
SubmitForm(Form1);;If(!IsBlankOrError( Form1.Error); Notify("Une erreur est survenue lors de la sauvegarde " & Form1.Error; NotificationType.Error);Notify("La savegarde a réussi";NotificationType.Information);;Set(currentElement; Form1.LastSubmit))
Sort columns
Set(Month, Distinct(SortByColumns(CurrentMonthMails, "Year", Ascending, "Month", Ascending), Month))
Set date
Set(StartDate, DateAdd(DateTimeValue( Day(Today) &"/"& Month(Today) &"/"& Year(Today) &" 00:00:00"), -30));
Sum
Sum(Filter(CurrentMonthMails, Month = ThisItem.Result ), uniqMails)
SharePoint RestShow Users List
On 28/10/2025

let currentSort = { column: null, direction: 'asc' }; // Store the current sort state
// Creates the style element
function createStyleElement(id, content) {
var style = document.createElement("style");
style.type = "text/css";
style.id = id;
style.innerHTML = content;
if (style.styleSheet) {
style.styleSheet.cssText = content;
} else {
let st = document.getElementById(id);
if (st == undefined) {
var head = document.head || document.getElementsByTagName("head")[i];
head.appendChild(style);
} else {
st.innerHTML = content;
}
}
return style;
}
// Function to filter the table based on dropdown selection
function filterTable(columnIndex, value) {
let table, tr, td, i, select, selectedValue, txtValue;
table = document.querySelector("table");
tr = table.getElementsByTagName("tbody")[0].getElementsByTagName("tr");
select = table.getElementsByTagName("select")[columnIndex];
//debugger;
selectedValue = value;
// Loop through all table rows and hide those that don't match the filter
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[columnIndex];
if (td) {
txtValue = td.textContent || td.innerText;
if (selectedValue === "" || txtValue === selectedValue) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
function sortTable(columnIndex, direction) {
let table, rows, switching, i, x, y, shouldSwitch;
table = document.querySelector("table");
switching = true;
let tbody = table.querySelector("tbody");
// Set the current sort state
currentSort.column = columnIndex;
currentSort.direction = direction;
while (switching) {
switching = false;
rows = tbody.rows;
for (i = 0; i < rows.length - 1; i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("td")[columnIndex];
y = rows[i + 1].getElementsByTagName("td")[columnIndex];
let isNumber = false;
if (!isNaN(x.innerHTML)) {
// Check if rows should switch based on ascending or descending order
if (direction === 'asc') {
if (parseFloat(x.innerHTML) > parseFloat(y.innerHTML)) {
shouldSwitch = true;
break;
}
} else if (direction === 'desc') {
if (parseFloat(x.innerHTML) < parseFloat(y.innerHTML)) {
shouldSwitch = true;
break;
}
}
}
else {
// Check if rows should switch based on ascending or descending order
if (direction === 'asc') {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
} else if (direction === 'desc') {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}
// Function to generate the table
function generateTableFromJson2(jsonArray, select, addHeaders = true) {
const style = `
body{
background-color: #f8f8f8;
}
.parentDiv{
height:400px;
overflow-x:scroll;
white-space: nowrap;
}
ul
{
list-style-type: none;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 8px 12px;
text-align: left;
border: 1px solid #ddd;
}
tbody tr{
max-height: 15px;
}
th {
background-color: #f4f4f4;
color: #000;
}
/* Scrollable table wrapper */
.table-wrapper {
height: 800px;
overflow-y: auto;
border: 1px solid #ddd;
overflow-x:scroll;
}
/* Style for dropdowns in header */
select {
width: 100%;
padding: 4px;
margin-top: 5px;
}
/* Style for the sorting arrows */
.sort-arrows {
cursor: pointer;
margin-left: 5px;
}
`;
createStyleElement("fdiStyle", style);
// Create table element
let table = document.createElement('table');
// Create table header
let header = table.createTHead();
let headerRow = header.insertRow(0);
// Get keys (headers) from the first object in the JSON array
//let keys = Object.keys(jsonArray[0]);
let keys = select.split(",");
if (addHeaders) {
keys.forEach((key, index) => {
if (key !== "__metadata") {
let th = document.createElement('th');
th.innerHTML = key;
// Create a dropdown (select) for filtering
let select = document.createElement('select');
select.addEventListener('change', function () {
const selectedValue = select.value;
filterTable(index, selectedValue);
});
// Populate dropdown with unique values from the JSON data
let uniqueValues = [...new Set(jsonArray.map(item => item[key]))];
// Add a default "All" option for no filter
let optionAll = document.createElement('option');
optionAll.value = "";
optionAll.text = `All`;
select.appendChild(optionAll);
// Create an option for each unique value
if (typeof (uniqueValues[0]) === typeof (1)) {
const pp = uniqueValues.sort((a, b) => {
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
});
pp.forEach(value => {
let option = document.createElement('option');
option.value = value;
option.text = value;
select.appendChild(option);
});
} else
uniqueValues.sort().forEach(value => {
let option = document.createElement('option');
option.value = value;
option.text = value;
select.appendChild(option);
});
// Sort arrows for sorting the columns
let upArrow = document.createElement('span');
upArrow.innerHTML = '⬆️';
upArrow.classList.add('sort-arrows');
upArrow.onclick = () => sortTable(index, 'asc');
let downArrow = document.createElement('span');
downArrow.innerHTML = '⬇️';
downArrow.classList.add('sort-arrows');
downArrow.onclick = () => sortTable(index, 'desc');
th.appendChild(select); // Append the dropdown to the header
th.appendChild(upArrow); // Append the dropdown to the header
th.appendChild(downArrow); // Append the dropdown to the header
headerRow.appendChild(th);
}
});
}
// Create table body and populate rows with data
let tbody = document.createElement('tbody');
jsonArray.forEach((item) => {
let row = tbody.insertRow();
keys = select.split(",");
keys.forEach((key) => {
let cell = row.insertCell();
if (key !== "__metadata") {
cell.setAttribute("nowrap", "nowrap");
if (key === "permissions") {
if (item.permissions !== undefined && item.permissions.length > 0) {
const ul = document.createElement('ul');
item.permissions.forEach((perm) => {
let li = document.createElement('li');
const tablePerm = document.createElement('table');
const tbodyPrem = document.createElement('tbody');
let rowPrem = tbodyPrem.insertRow();
let cellPerm = rowPrem.insertCell();
//member
cellPerm.appendChild(generateTableFromJson2([perm.Member], "LoginName,Title", false))
//perms
cellPerm = rowPrem.insertCell();
cellPerm.appendChild(generateTableFromJson2(perm.RoleDefinitionBindings.results, "Name", false));
tablePerm.appendChild(tbodyPrem);
li.appendChild(tablePerm);
ul.appendChild(li);
});
cell.appendChild(ul);
} else {
cell.innerHTML = " ";
}
} else if (key.indexOf("/") > 0) {
cell.innerHTML = item[key.split("/")[0]][key.split("/")[1]]
} else
cell.innerHTML = item[key]; // Insert each value from the JSON into the table cell
}
});
});
// Append the body to the table
table.appendChild(tbody);
return table;
}
function removeSlasches(select, datas) {
const ret = [];
const fields = select.split(',');
for (let i = 0; i < datas.length; i++) {
const toAdd = {};
for (let j = 0; j < fields.length; j++) {
if (fields[j].indexOf('/') > 0) {
const splitted = fields[j].split('/');
toAdd[splitted.join('')] = datas[i][splitted[0]][splitted[1]];
} else
toAdd[fields[j]] = datas[i][fields[j]];
}
ret.push(toAdd);
}
console.log("removeSlasches", ret);
return ret;
}
async function GetDigestValue(siteUrl) {//
const fetchOptions = {
method: 'POST',
headers: {
'Accept': 'application/json;odata=verbose',
'Content-type': 'application/json;odata=verbose'
}
};
const response = await fetch(siteUrl + "/_api/contextinfo", fetchOptions);
return (await response.json()).d.GetContextWebInformation.FormDigestValue;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function ExecuteQuery(req, fetchOptions, maxRetry = 3, wait = 1, trynum = 1) {
console.log("ExecuteQuery", req, fetchOptions, maxRetry, wait, trynum);
if (trynum >= maxRetry) {
console.log("ExecuteQuery Error", req);
console.log("ExecuteQuery Error", fetchOptions);
throw new Error(`ExecuteQuery error! maxRetry >= trynum`);
}
try {
let startDate = new Date();
let diffMinutes = 0;
respList1 = await fetch(req, fetchOptions);
endDate = new Date();
const diffMs = endDate - startDate;
diffMinutes = Math.floor(diffMs / (1000));
console.log(`seconds ${diffMinutes} queryNumber ${trynum}`)
//avoid 429 too much queries
if (!respList1.ok && respList1.status == 429) {
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
await sleep(wait * 10);// * trynum
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
} else if (!respList1.ok && respList1.status == 503) {//avoid 503 server unavailable / connections error
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
await sleep(wait * 10);// * trynum
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
} else if (!respList1.ok && respList1.status == 403) {//avoid 403 reload page in another tab
//debugger;
window.open(_spPageContextInfo.webAbsoluteUrl, '_blank')
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
await sleep(wait * 10);// * trynum
window.open(_spPageContextInfo.webAbsoluteUrl, '_blank')
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
} else if (!respList1.ok) {
console.log("ExecuteQuery Error", respList1);
const errorDetails = await respList1.text(); // Get error details from the response
console.log("ExecuteQuery Error", respList1);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${errorDetails}`);
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
console.log(err.error.message.value);
throw new Error(`HTTP error! Status: ${respList1.status}`);
}
return respList1
} catch (error) {
console.log(error);
throw new Error(`HTTP error! Status: ${error}`);
}
}
const siteUrl = _spPageContextInfo.webAbsoluteUrl;
const fetchOptions = {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
};
//get web server relative url
let resp = await ExecuteQuery(`${siteUrl}/_api/web?$select=ServerRelativeUrl`, fetchOptions);
let usrType1 = await resp.json();
console.log(usrType1.d);
const webRelativeUrl = usrType1.d.ServerRelativeUrl;
//get user list
resp = await ExecuteQuery(`${siteUrl}/_api/web/lists?$select=RootFolder/ServerRelativeUrl,Id&$expand=RootFolder`, fetchOptions);
usrType1 = await resp.json();
let userListId = "";
usrType1.d.results.forEach(list => {
if (list.RootFolder.ServerRelativeUrl.toLowerCase() === (webRelativeUrl + "/_api/web/siteuserinfolist").toLowerCase() ||
list.RootFolder.ServerRelativeUrl.toLowerCase() === (webRelativeUrl + "/_catalogs/users").toLowerCase()) {
userListId = list.Id;
}
});
if(userListId === ""){
console.log("list not found");
throw new Error("list not found");
}
resp = await ExecuteQuery(`${siteUrl}/_api/web/lists(guid'${userListId}')/items?$select=FirstName,IsActive,LastName,UserName,Modified,Author/Title,JobTitle,Department,IsSiteAdmin,EMail,Title,Name,ContentTypeDisp,Deleted,PrincipalCount,ID&$expand=Author`, fetchOptions);
let j = await resp.json();
console.log(j.d);
resp = await ExecuteQuery(`${siteUrl}/_api/web/siteusers?$select=ID,PrincipalType,IsShareByEmailGuestUser`, fetchOptions);
const usrType = await resp.json();
j.d.results.forEach(element => {
//debugger;
const usr = usrType.d.results.find(u => u.Id === element.ID);
//console.log("usrType", usrType);
if (usr !== undefined) {
element.PrincipalType = usr.PrincipalType;
element.IsShareByEmailGuestUser = usr.IsShareByEmailGuestUser;
} else {
element.PrincipalType = -1;
element.IsShareByEmailGuestUser = false;
}
});
document.body.innerHTML = ``;
const table = generateTableFromJson2(j.d.results, "EMail,Title,PrincipalType,IsShareByEmailGuestUser,Name,IsActive,FirstName,LastName,UserName,Modified,Author/Title,JobTitle,Department,IsSiteAdmin,Deleted,ID");
// Append the table to the container
document.getElementById('tableContainer').appendChild(table);
Sharepoint Audit List Permissions batch
On 17/10/2025
const siteUrl = _spPageContextInfo.webAbsoluteUrl;
const listUrl = "Shared%20Documents";
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function generateGuid() {
await sleep(10);// * trynum
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
async function getRequestDigest() {
const fetchOptions = {
method: "POST",
headers: { Accept: "application/json;odata=verbose" },
credentials: "include",
};
const data = (await (await ExecuteQuery(`${siteUrl}/_api/contextinfo`, fetchOptions)).json());
return data.d.GetContextWebInformation.FormDigestValue;
}
async function ExecuteQuery(req, fetchOptions, maxRetry = 3, wait = 10000, trynum = 1) {
console.log("ExecuteQuery", req, fetchOptions, maxRetry, wait, trynum);
if (trynum >= maxRetry) {
console.log("ExecuteQuery Error", req);
console.log("ExecuteQuery Error", fetchOptions);
throw new Error(`ExecuteQuery error! maxRetry >= trynum`);
}
try {
let startDate = new Date();
let diffMinutes = 0;
respList1 = await fetch(req, fetchOptions);
endDate = new Date();
const diffMs = endDate - startDate;
diffMinutes = Math.floor(diffMs / (1000));
console.log(`seconds ${diffMinutes} queryNumber ${trynum}`)
//avoid 429 too much queries
if (!respList1.ok && respList1.status == 429) {
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
await sleep(wait * 2);// * trynum
if (fetchOptions.method === "POST") {
//regnerate the digest
fetchOptions["X-RequestDigest"] = await getRequestDigest();
}
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
}
//avoid 503 server unavailable / connections error
if (!respList1.ok && respList1.status == 503) {
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
await sleep(1000 * wait);// wait 10 seconds
if (fetchOptions.method === "POST") {
//regnerate the digest
fetchOptions["X-RequestDigest"] = await getRequestDigest();
}
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
}
//avoid 403 reload page in another tab
if (!respList1.ok && respList1.status == 403) {
//debugger;
window.open(siteUrl, '_blank')
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
console.log("waiting due to error 403");
await sleep(10000);// wait 10 seconds
window.open(siteUrl, '_blank')
await sleep(1000 * wait);// wait 10 seconds
if (fetchOptions.method === "POST") {
//regnerate the digest
fetchOptions["X-RequestDigest"] = await getRequestDigest();
}
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
}
if (!respList1.ok) {
console.log("ExecuteQuery Error", respList1);
const errorDetails = await respList1.text(); // Get error details from the response
console.log("ExecuteQuery Error", respList1);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${errorDetails}`);
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
console.log(err.error.message.value);
throw new Error(`HTTP error! Status: ${respList1.status}`);
}
return respList1
} catch (error) {
console.log(error);
throw new Error(`HTTP error! Status: ${error}`);
}
}
async function GetFolderSize(siteUrl, listUrl1, query) {
// Fetch options with headers for authentication and response format
const fetchOptions = {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
};
//get web relativeUrl
var req = `${siteUrl}/_api/web?$select=ServerRelativeUrl`;
const webServerRelativUrl = (await (await ExecuteQuery(req, fetchOptions)).json()).d.ServerRelativeUrl;
// get total items count
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/?$select=ItemCount`;
const ItemsCount = (await (await ExecuteQuery(req, fetchOptions)).json()).d.ItemCount;
let query1 = "";
if (`${query}`.trim() !== "") {
query1 = `&$filter=${query}`;
query = ` and ${query}`;
}
//get firstId
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items?$select=Id&$top=1&$orderby=Id asc${query1}`;
console.log("req", req);
const firstId = (await (await ExecuteQuery(req, fetchOptions)).json()).d.results[0].Id;
console.log("firstId", firstId);
//get lastId
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items?$select=Id&$top=1&$orderby=Id desc${query1}`;
console.log("last", req);
const lastId = (await (await ExecuteQuery(req, fetchOptions)).json()).d.results[0].Id;
console.log("lastId", lastId);
let startId = firstId;
let endId = firstId + 5000;
var allItems = [];
console.log(`startId ${startId} endId ${endId} lastId ${lastId}`);//FileSizeDisplay
console.log("query", query);//_UIVersionString File_x0020_Size
const startDate = new Date();
let endDate = new Date();
let diffMinutes = 0;
let queryNumber = 1;
do {
//to avoid 429 error
if (queryNumber % 10 == 0) {
console.log(`sleep 1 minute queryNumber ${queryNumber}`);
await sleep(60000); // 60 000 ms = 1 minute
}
var select = "?$select=File/Length,File/UIVersionLabel,File_x0020_Type,Id,HasUniqueRoleAssignments,FileRef,FileLeafRef,FileDirRef,Created,Modified,Author/Title,Author/EMail,Editor/Title,Editor/EMail,ContentTypeId";
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items${select}&$filter=Id ge ${startId} and Id lt ${endId} and Id le ${lastId}${query}&$orderby=Id asc&$top=5000&$expand=File,Author,Editor`;
console.log("req", req);
// Send the asynchronous GET request to the REST API endpoint /_api/site/usage
let respList1 = null;
try {
respList1 = await ExecuteQuery(req, fetchOptions);
endDate = new Date();
queryNumber++;
} catch (error) {
console.log("error", error);
return allItems;
}
const items = (await respList1.json()).d.results;
allItems.push(...items);
startId += 5000;
endId += 5000;
const diffMs = endDate - startDate;
diffMinutes = Math.floor(diffMs / (1000 * 60));
console.log(`startId ${startId} endId ${endId} lastId ${lastId} diffMinutes ${diffMinutes} queryNumber ${queryNumber}, ItemsCount : ${ItemsCount}`)
await sleep(1500); // 1,5 second
//debugger;
}
while (startId <= lastId);
return allItems;
}
async function batchFetchPermissions(queriess) {
const queries = [...queriess];
console.log("batchFetchPermissions", queries);
const batchBoundary = "batch_" + await generateGuid();
const batchBody = queries.map((query) => {
return `
--${batchBoundary}
Content-Type: application/http
Content-Transfer-Encoding: binary
GET ${query.req} HTTP/1.1
Accept: application/json;odata=verbose
`;
}).join("\n") + `\n--${batchBoundary}--`;
const digest = await getRequestDigest();//
console.log("batchBody", batchBody.length);
const headers = {
Accept: "application/json;odata=verbose",
"X-RequestDigest": digest,
"Content-Type": `multipart/mixed; boundary="${batchBoundary}"`,
};
const response = await fetch(`${siteUrl}/_api/$batch`, {
method: "POST",
headers,
body: batchBody,
});
const text = await response.text(); // Parse response manually (multipart)
const responses = text.split("HTTP/1.1 200 OK");
const results1 = [];
for (let k = 1; k < responses.length; k++) {
const parts = responses[k].split("\r\n\r\n")[1];
// The JSON is the last part after the headers
let jsonString = parts[parts.length - 1];
// Parse the JSON
jsonString = parts.split("\r\n")[0];
const d = {
Id: `${queries[k - 1].Id}`,
Index: k,
result: JSON.parse(jsonString.trim()).d
}
results1.push(d);
}
return [...results1];
}
const maxBatch = 20;
async function LoadUniquePermissions(items) {
let batchCount = 0;
let requests = [];
var req = `${siteUrl}/_api/web?$select=ServerRelativeUrl`;
const fetchOptions = {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
};
const perms = [];
const webServerRelativUrl = (await (await ExecuteQuery(req, fetchOptions)).json()).d.ServerRelativeUrl;
for (let i = 0; i < items.length; i++) {
items[i].permId = await generateGuid();
if (items[i].HasUniqueRoleAssignments) {
requests.push({
Id: items[i].permId,
req: `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl}')/items(${items[i].Id})/RoleAssignments?$expand=Member,RoleDefinitionBindings&$select=Member/Id,Member/LoginName,Member/Title,RoleDefinitionBindings/Name`
});
batchCount++;
}
if (requests.length === maxBatch) {
perms.push(await batchFetchPermissions(requests));
requests = [];
}
}
if (requests.length > 0) {
perms.push(await batchFetchPermissions(requests));
requests = [];
}
for (let i = 0; i < items.length; i++) {
const perm = perms.flat().filter(f => `${f.Id}` == `${items[i].permId}`);
if (items[i].HasUniqueRoleAssignments && perm.length === 1) {
items[i].permissions = perm[0].result.results;
}
}
console.log("with perm", items);
return items;
}
const disgest = await getRequestDigest();
console.log("disgest", disgest);
const items = await GetFolderSize(siteUrl, listUrl, "Id le 145000");//(Id eq 225 or Id eq 226) Id gt 270
const rest = await LoadUniquePermissions(items);
SharePoint Get Doc Lib Size avoid error 429
On 10/10/2025
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function ExecuteQuery(req, fetchOptions, maxRetry = 3, wait = 1, trynum = 1) {
console.log("ExecuteQuery", req, fetchOptions, maxRetry, wait, trynum);
if (trynum >= maxRetry) {
console.log("ExecuteQuery Error", req);
console.log("ExecuteQuery Error", fetchOptions);
throw new Error(`ExecuteQuery error! maxRetry >= trynum`);
}
try {
let startDate = new Date();
let diffMinutes = 0;
respList1 = await fetch(req, fetchOptions);
endDate = new Date();
const diffMs = endDate - startDate;
diffMinutes = Math.floor(diffMs / (1000));
console.log(`seconds ${diffMinutes} queryNumber ${trynum}`)
//avoid 429 too much queries
if (!respList1.ok && respList1.status == 429) {
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
await sleep(wait * 10);// * trynum
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
}
//avoid 503 server unavailable / connections error
if (!respList1.ok && respList1.status == 503) {
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
await sleep(wait * 10);// * trynum
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
}
//avoid 403 reload page in another tab
if (!respList1.ok && respList1.status == 403) {
//debugger;
window.open(_spPageContextInfo.webAbsoluteUrl, '_blank')
const errorDetails = await respList1.text(); // Get error details from the response
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
await sleep(wait * 10);// * trynum
window.open(_spPageContextInfo.webAbsoluteUrl, '_blank')
return await ExecuteQuery(req, fetchOptions, maxRetry, (wait * 5), ++trynum);
}
if (!respList1.ok) {
console.log("ExecuteQuery Error", respList1);
const errorDetails = await respList1.text(); // Get error details from the response
console.log("ExecuteQuery Error", respList1);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${errorDetails}`);
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
console.log(err.error.message.value);
throw new Error(`HTTP error! Status: ${respList1.status}`);
}
return respList1
} catch (error) {
console.log(error);
throw new Error(`HTTP error! Status: ${error}`);
}
}
async function GetFolderSize(siteUrl, listUrl1, query) {
// Fetch options with headers for authentication and response format
const fetchOptions = {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
};
//get web relativeUrl
var req = `${siteUrl}/_api/web?$select=ServerRelativeUrl`;
const webServerRelativUrl = (await (await ExecuteQuery(req, fetchOptions)).json()).d.ServerRelativeUrl;
// get total items count
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/?$select=ItemCount`;
const ItemsCount = (await (await ExecuteQuery(req, fetchOptions)).json()).d.ItemCount;
let query1 = "";
if (`${query}`.trim() !== "") {
query1 = `&$filter=${query}`;
query = ` and ${query}`;
}
//get firstId
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items?$select=Id&$top=1&$orderby=Id asc${query1}`;
console.log("req", req);
const firstId = (await (await ExecuteQuery(req, fetchOptions)).json()).d.results[0].Id;
console.log("firstId", firstId);
//get lastId
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items?$select=Id&$top=1&$orderby=Id desc${query1}`;
console.log("last", req);
const lastId = (await (await ExecuteQuery(req, fetchOptions)).json()).d.results[0].Id;
console.log("lastId", lastId);
let startId = firstId;
let endId = firstId + 5000;
var allItems = [];
console.log(`startId ${startId} endId ${endId} lastId ${lastId}`);//FileSizeDisplay
console.log("query", query);//_UIVersionString File_x0020_Size
const startDate = new Date();
let endDate = new Date();
let diffMinutes = 0;
let queryNumber = 1;
do {
//to avoid 429 error
if (queryNumber % 10 == 0) {
console.log(`sleep 1 minute queryNumber ${queryNumber}`);
await sleep(60000); // 60 000 ms = 1 minute
}
var select = "?$select=File/Length,File/UIVersionLabel,File_x0020_Type,Id,HasUniqueRoleAssignments,FileRef,FileLeafRef,FileDirRef,Created,Modified,Author/Title,Author/EMail,Editor/Title,Editor/EMail,ContentTypeId";
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items${select}&$filter=Id ge ${startId} and Id lt ${endId} and Id le ${lastId}${query}&$orderby=Id asc&$top=5000&$expand=File,Author,Editor`;
console.log("req", req);
// Send the asynchronous GET request to the REST API endpoint /_api/site/usage
let respList1 = null;
try {
respList1 = await ExecuteQuery(req, fetchOptions);
endDate = new Date();
queryNumber++;
} catch (error) {
console.log("error", error);
return allItems;
}
const items = (await respList1.json()).d.results;
allItems.push(...items);
startId += 5000;
endId += 5000;
const diffMs = endDate - startDate;
diffMinutes = Math.floor(diffMs / (1000 * 60));
console.log(`startId ${startId} endId ${endId} lastId ${lastId} diffMinutes ${diffMinutes} queryNumber ${queryNumber}, ItemsCount : ${ItemsCount}`)
await sleep(1500); // 1,5 second
//debugger;
}
while (startId <= lastId);
//console.log("allItems", allItems);
console.log("queryNumber", queryNumber);
return allItems;
}
let totalSize = 0
const siteUrl = _spPageContextInfo.webAbsoluteUrl;
const items = await GetFolderSize(siteUrl, "Shared%20Documents", "");//startswith(ContentTypeId,'0x0101')
//calculate file Size
let separator = ";"
let csv = `Id${separator}HasUniqueRoleAssignments${separator}FromParent${separator}Title${separator}FileRef${separator}FileDirRef${separator}FileLeafRef${separator}Created${separator}CreatedMin${separator}Modified${separator}ModifiedMin${separator}AuthorTitle${separator}AuthorEMail${separator}EditorTitle${separator}EditorEMail${separator}FileLength${separator}MB${separator}GB${separator}FileUIVersionLabel${separator}File_x0020_Type${separator}ContentTypeId${separator}count\n`;
//display lastID
if (items !== undefined && items !== null && items.length > 0) {
console.log(`lastId ${items[items.length - 1].Id}`);
}
//check child
//get folders with unique permissions
const folder = items.filter(file => file.HasUniqueRoleAssignments && file.ContentTypeId.startsWith('0x0120'));
for (let k = 0; k < folder.length; k++) {
for (let i = 0; i < items.length; i++) {
if(items[i].FromParent == undefined)
items[i].FromParent = false;
if (items[i].HasUniqueRoleAssignments == false && items[i].FileDirRef.startsWith(folder[k].FileRef)) {
items[i].HasUniqueRoleAssignments = true;
items[i].FromParent = true;
}
}
}
for (let i = 0; i < items.length; i++) {
csv += `${items[i].Id}${separator}`;
csv += `${items[i].HasUniqueRoleAssignments}${separator}`;
csv += `${items[i].FromParent}${separator}`;
csv += `${items[i].Title}${separator}`;
csv += `${items[i].FileRef}${separator}`;
csv += `${items[i].FileDirRef}${separator}`;
csv += `${items[i].FileLeafRef}${separator}`;
csv += `${items[i].Created}${separator}`;
csv += `${items[i].Created.substring(0, 10)}${separator}`;
csv += `${items[i].Modified}${separator}`;
csv += `${items[i].Modified.substring(0, 10)}${separator}`;
csv += `${items[i].Author.Title}${separator}`;
csv += `${items[i].Author.EMail}${separator}`;
csv += `${items[i].Editor.Title}${separator}`;
csv += `${items[i].Editor.EMail}${separator}`;
//if is a file
if (items[i].File != undefined && items[i].File.Length != undefined) {
totalSize += parseInt(items[i].File.Length);
csv += `${items[i].File.Length}${separator}`;
csv += `${(items[i].File.Length / (1024 * 1024)).toFixed(2)}${separator}`;
csv += `${(items[i].File.Length / (1024 * 1024 * 1024)).toFixed(2)}${separator}`;
csv += `${items[i].File.UIVersionLabel}${separator}`;
csv += `${items[i].File_x0020_Type}${separator}`;
}
else {
//is folder
csv += `${separator}`;
csv += `${separator}`;
csv += `${separator}`;
csv += `${separator}`;
csv += `${separator}`;
}
csv += (`${items[i].ContentTypeId}`.startsWith('0x0120') ? "folder" : `${items[i].ContentTypeId}`);
csv += `${separator}1\n`;
}
const totalSizeGB = (totalSize / (1024 * 1024 * 1024)).toFixed(2);
console.log("totalSize B", totalSize);
console.log("total size MB", (totalSize / (1024 * 1024)).toFixed(2));
console.log("total size GB", totalSizeGB);
console.log("items length", items.length);
console.log("csv", csv);
console.log("items", items);
Get SharePoint Document Library Size
On 09/10/2025
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function GetFolderSize(siteUrl, listUrl1, query) {
// Fetch options with headers for authentication and response format
const fetchOptions = {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
};
// get web relativeUrl
var req = `${siteUrl}/_api/web?$select=ServerRelativeUrl`;
const webServerRelativUrl = (await (await fetch(req, fetchOptions)).json()).d.ServerRelativeUrl;
let query1 = "";
if (`${query}`.trim() !== "") {
query1 = `&$filter=${query}`;
query = ` and ${query}`;
}
// get firstId
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items?$select=Id&$top=1&$orderby=Id asc`;
console.log("req", req);
const firstId = 0;
console.log("firstId", firstId);
// get lastId
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items?$select=Id&$top=1&$orderby=Id desc`;
console.log("last", req);
const lastId = (await (await fetch(req, fetchOptions)).json()).d.results[0].Id;
console.log("lastId", lastId);
let startId = firstId;
let endId = firstId + 5000;
var allItems = [];
console.log(`startId ${startId} endId ${endId} lastId ${lastId}`);
console.log("query", query);
const startDate = new Date();
let endDate = new Date();
let diffMinutes = 0;
let queryNumber = 0;
do {
// to avoid 429 error
if(queryNumber % 10 == 0){
await sleep(60000); // 60 000 ms = 1 minute
}
var select = "?$select=File/Length";
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items${select}&$filter=Id ge ${startId} and Id lt ${endId}${query}&$orderby=Id asc&$top=5000&$expand=File`;
console.log("req", req);
let respList1 = null;
try {
respList1 = await fetch(req, fetchOptions);
if (!respList1.ok) {
const errorDetails = await respList1.text();
console.error(`HTTP error! Status: ${respList1.status}, Details: ${errorDetails}`);
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
console.log(err.error.message.value);
throw new Error(`HTTP error! Status: ${respList1.status}`);
}
endDate = new Date();
queryNumbercatch (error) {
console.log("error", error);
return null;
}
const items = (await respList1.json()).d.results;
allItems.push(...items);
startId += 5000;
endId += 5000;
const diffMs = endDate - startDate;
diffMinutes = Math.floor(diffMs / (1000 * 60));
console.log(`startId ${startId} endId ${endId} lastId ${lastId} diffMinutes ${diffMinutes} queryNumber ${queryNumber}`)
}
while (endId < lastId);
console.log("queryNumber", queryNumber);
return allItems;
}
let totalSize = 0
const siteUrl = "Your site Url";
const items = await GetFolderSize(siteUrl, "Your doclib Name", "startswith(ContentTypeId,'0x0101')");
// calculate file Size
for (let i = 0; i < items.length; i++) {
if (items[i].File != undefined && items[i].File.Length != undefined) {
totalSize += parseInt(items[i].File.Length);
}
}
const totalSizeGB = (totalSize / (1024 * 1024 * 1024)).toFixed(2);
console.log("totalSize B", totalSize);
console.log("total size MB", (totalSize / (1024 * 1024)).toFixed(2));
console.log("total size GB", totalSizeGB);
console.log("items length", items.length);
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function GetFolderSize(siteUrl, listUrl1, query) {
// Fetch options with headers for authentication and response format
const fetchOptions = {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
};
//get web relativeUrl
var req = `${siteUrl}/_api/web?$select=ServerRelativeUrl`;
const webServerRelativUrl = (await (await fetch(req, fetchOptions)).json()).d.ServerRelativeUrl;
let query1 = "";
if (`${query}`.trim() !== "") {
query1 = `&$filter=${query}`;
query = ` and ${query}`;
}
//get firstId
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items?$select=Id&$top=1&$orderby=Id asc`;
console.log("req", req);
const firstId = 0;
console.log("firstId", firstId);
//get lastId
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items?$select=Id&$top=1&$orderby=Id desc`;
console.log("last", req);
const lastId = (await (await fetch(req, fetchOptions)).json()).d.results[0].Id;
console.log("lastId", lastId);
let startId = firstId;
let endId = firstId + 5000;
var allItems = [];
console.log(`startId ${startId} endId ${endId} lastId ${lastId}`);//FileSizeDisplay
console.log("query", query);//_UIVersionString File_x0020_Size
const startDate = new Date();
let endDate = new Date();
let diffMinutes = 0;
let queryNumber = 0;
do {
//to avoid 429 error
if(queryNumber % 10 == 0){
await sleep(60000); // 60 000 ms = 1 minute
}
var select = "?$select=File/Length";
req = `${siteUrl}/_api/web/getlist('${webServerRelativUrl}/${listUrl1}')/items${select}&$filter=Id ge ${startId} and Id lt ${endId}${query}&$orderby=Id asc&$top=5000&$expand=File`;
console.log("req", req);
// Send the asynchronous GET request to the REST API endpoint /_api/site/usage
let respList1 = null;
try {
respList1 = await fetch(req, fetchOptions);
if (!respList1.ok) {
const errorDetails = await respList1.text(); // Get error details from the response
console.error(`HTTP error! Status: ${respList1.status}, Details: ${errorDetails}`);
let err = JSON.parse(errorDetails);
console.error(`HTTP error! Status: ${respList1.status}, Details: ${err.error.message.value}`);
console.log(err.error.message.value);
throw new Error(`HTTP error! Status: ${respList1.status}`);
}
endDate = new Date();
queryNumber++;
} catch (error) {
console.log("error", error);
return null;
}
const items = (await respList1.json()).d.results;
allItems.push(...items);
startId += 5000;
endId += 5000;
const diffMs = endDate - startDate;
diffMinutes = Math.floor(diffMs / (1000 * 60));
console.log(`startId ${startId} endId ${endId} lastId ${lastId} diffMinutes ${diffMinutes} queryNumber ${queryNumber}`)
}
while (endId < lastId);
//console.log("allItems", allItems);
console.log("queryNumber", queryNumber);
return allItems;
}
let totalSize = 0
const siteUrl = "Your site Url";
const items = await GetFolderSize(siteUrl, "Your doclib Name", "startswith(ContentTypeId,'0x0101')");
//calculate file Size
for (let i = 0; i < items.length; i++) {
if (items[i].File != undefined && items[i].File.Length != undefined) {
totalSize += parseInt(items[i].File.Length);
}
}
const totalSizeGB = (totalSize / (1024 * 1024 * 1024)).toFixed(2);
console.log("totalSize B", totalSize);
console.log("total size MB", (totalSize / (1024 * 1024)).toFixed(2));
console.log("total size GB", totalSizeGB);
console.log("items length", items.length);
//console.log("items", items);
Sharepoint Web Templates List
On 07/10/2025
Modèles de sites SharePoint modernes (2025)
| Code du modèle | Nom du modèle | Description | Type de site associé |
|---|---|---|---|
| STS#3 | Site d’équipe (Team Site) | Site de collaboration pour les équipes, avec bibliothèques de documents, listes de tâches, calendrier et intégration avec Microsoft Teams. | Groupe Microsoft 365/Teams |
| GROUP#0 | Site d’équipe moderne | Équivalent moderne de STS#3, toujours lié à un groupe Microsoft 365 (et donc à Teams si activé). | Groupe Microsoft 365/Teams |
| SITEPAGEPUBLISHING#0 | Site de communication (Communication Site) | Pour diffuser des informations (actualités, rapports, événements) à large audience. Pas lié à Teams. | Site autonome |
| COMMSITE#0 | Site de communication moderne | Version moderne du site de publication, optimisé pour la communication visuelle et les composants web. | Site autonome |
| STS#0 | Site vide (Blank Site) | Site SharePoint vide, sans listes ni bibliothèques préconfigurées. | Site autonome |
| BDR#0 | Centre de documents | Pour gérer et organiser des documents en masse, souvent utilisé comme archive. | Site autonome |
| SRCHCEN#0 | Centre de recherche | Site dédié à la recherche avancée dans SharePoint. | Site autonome |
| SRCHCENTERLITE#0 | Centre de recherche léger | Version simplifiée du centre de recherche. | Site autonome |
| EDISC#0 | Centre de découverte électronique | Pour la gestion des données dans un contexte juridique ou de conformité. | Site autonome |
| POINTPUBLISHING#0 | Site de publication | Pour publier des pages web avec flux de travail d’approbation (classique). | Site autonome |
2. Modèles classiques (moins utilisés en 2025, mais toujours disponibles)
| Code du modèle | Nom du modèle | Description |
|---|---|---|
| STS#1 | Site d’équipe classique | Ancienne version du site d’équipe, sans intégration moderne avec Teams. |
| STS#2 | Site d’équipe vide | Site d’équipe sans contenu préconfiguré. |
| WIKI#0 | Site Wiki | Pour créer une base de connaissances collaborative sous forme de wiki. |
| BLOG#0 | Site de blog | Pour publier des articles sous forme de blog. |
| DEV#0 | Site de développement | Pour les développeurs, avec des listes de suivi de bugs et de tâches. |
| PROJECTSITE#0 | Site de projet | Pour gérer des projets, avec des listes de tâches et des jalons. |
| COMMUNITY#0 | Site communautaire | Pour créer une communauté avec forums de discussion. |
| VISPRJS#0 | Référentiel Visio | Pour stocker et partager des diagrammes Visio. |
Sharepoint React SPFX issue scss missing
On 24/09/2025
in my react code below i have and an error : Cannot find module '../View.module.scss' or its corresponding type declarations.
import styles from './View.module.scss';
To solve it verify this fils exists
View.module.scss.ts was missing with code below, so i add it
require("./View.module.css");
const styles = {
genericView: 'genericView_c46baf68',
countryview: 'countryview_c46baf68',
tableContainer: 'tableContainer_c46baf68',
filterLabel: 'filterLabel_c46baf68',
cell: 'cell_c46baf68',
buttonCell: 'buttonCell_c46baf68',
clearButton: 'clearButton_c46baf68',
detailsList: 'detailsList_c46baf68',
detailsListValue: 'detailsListValue_c46baf68',
iconGreen: 'iconGreen_c46baf68',
iconRed: 'iconRed_c46baf68',
field: 'field_c46baf68',
fieldLabel: 'fieldLabel_c46baf68',
fieldLabelContainer: 'fieldLabelContainer_c46baf68',
fieldValue: 'fieldValue_c46baf68',
fieldLower: 'fieldLower_c46baf68',
spinnerContainer: 'spinnerContainer_c46baf68',
noItems: 'noItems_c46baf68',
callout: 'callout_c46baf68',
viewDescription: 'viewDescription_c46baf68',
emptyItem: 'emptyItem_c46baf68',
statusActive: 'statusActive_c46baf68',
statusInactive: 'statusInactive_c46baf68',
statusDissolved: 'statusDissolved_c46baf68'
};
export default styles;
Pnp PowerShell Export Import Site
On 02/07/2025
Define JSON configuration https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/configuring-the-pnp-provisioning-engine
Connect-PnPOnline -Url $siteUrl -ClientId $clientId -Tenant $tenantName -Thumbprint $cert
$xml = Get-PnPSiteTemplate -Out $SchmaXMLPath -Configuration $configPath
# Invoke-PnPSiteTemplate -Path $SchmaXMLPath
{
"$schema": "https://aka.ms/sppnp-extract-configuration-schema",
"handlers": [
"ContentTypes",
"Fields",
"Lists"
],
"persistAssetFiles": false,
"lists": {
"lists": [
{
"title": "Eutelsat Entity",
"includeItems": false,
"query": {
"includeAttachments": false
}
}
]
},
"contentTypes": {
"groups": [
"Market Access"
]
}
}
# remove particular nodes
$SchmaXMLPathDest = "MA_pmsatEntity_15.xml"
[xml]$xmlContent = Get-Content $SchmaXMLPath
Clear-Host
# Define the namespace if needed (common in SharePoint XML)
$nsmgr = New-Object System.Xml.XmlNamespaceManager($xmlContent.NameTable)
# Add the namespace you are using in the XML document. Use "ns" as a prefix here.
$nsmgr.AddNamespace("pnp", "http://schemas.dev.office.com/PnP/2022/09/ProvisioningSchema")
# Use XPath to select fields. Adjust the XPath query based on your XML structure.
$fields = $xmlContent.SelectNodes("//Field", $nsmgr)
Write-Host "cout $($fields.Count)"
# Iterate over fields and remove those whose InternalName starts with an underscore
for ($i = $fields.Count - 1; $i -ge 0; $i--) {
$internalName = $fields[$i].Attributes["Name"].Value
if ($internalName -like "_*") {
# Remove the field from its parent node
$fields[$i].ParentNode.RemoveChild($fields[$i]) | Out-Null
continue;
}
$internalName = $fields[$i].Attributes["Group"].Value
if ($internalName -eq "_Hidden") {
# Remove the field from its parent node
$fields[$i].ParentNode.RemoveChild($fields[$i]) | Out-Null
}
}
$fields = $xmlContent.SelectNodes("//pnp:ContentType", $nsmgr)
for ($i = $fields.Count - 1; $i -ge 0; $i--) {
$internalName = $fields[$i].Attributes["Name"].Value
if ($internalName -ne "MA_EutelsatEntity") {
# Remove the field from its parent node
$fields[$i].ParentNode.RemoveChild($fields[$i]) | Out-Null
}
}
# Save the modified XML back to a file
$xmlContent.Save("{0}\template\test2.xml" -f (get-location))
Sharepoint Rest Get User ID By Mail
On 23/06/2025
async function GetDigestValue(siteUrl) {//
const fetchOptions = {
method: 'POST',
headers: {
'Accept': 'application/json;odata=verbose',
'Content-type': 'application/json;odata=verbose'
}
};
const response = await fetch(siteUrl + "/_api/contextinfo", fetchOptions);
return (await response.json()).d.GetContextWebInformation.FormDigestValue;
}
async function EnsureUser(siteUrl, userEmail) {
const digest = await GetDigestValue(siteUrl);
console.log("digest", digest);
const body = {
'logonName': `i:0#.f|membership|${userEmail}`
}
const response = await fetch(`${siteUrl}/_api/web/ensureuser?$select=Id`, {
method: "POST",
headers: {
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"X-RequestDigest": digest
},
body: JSON.stringify({
'logonName': `i:0#.f|membership|${userEmail}`
})
});
console.log("response", response);
const userData = await response.json();
return userData.d.Id;
}
async function getUserIdByEmail(siteUrl, userEmail) {
try {
const fetchOptions = {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose',
'Content-type': 'application/json;odata=verbose'
}
};
const response = await fetch(siteUrl + `/_api/web/siteusers/getbyemail('${encodeURIComponent(userEmail)}')`, fetchOptions);
const data = await response.json();
console.log("getUserByEmail data", data);
return data.d.Id;
} catch (error) {
console.log("getUserByEmail Error", error);
return null;
}
}
let siteUrl1 = "https://eutelsatgroup.sharepoint.com/sites/fdiSandBox";
let email1 = "ffdietrich-ext@eutelsat.com";
let ret = await EnsureUser(siteUrl1, email1);
console.log("response", ret);
const siteUrl = "https://test.sharepoint.com/sites/Dev_wf";
const email = "fpalmo@test.com";
console.log("response", ret0);
const ret = await EnsureUser(siteUrl, email);
const ret0 = await getUserIdByEmail(siteUrl, email);
console.log("response", ret);
Show Lists Roleassignments
On 27/05/2025
// Fonction pour récupérer tous les RoleDefinitionBindings
async function getRoleDefinitionBindings(list, Id, Title, ServerRelativeUrl, ItemsCount, Hidden, HasUniqueRoleAssignments) {
let p = `vdfvd`;//$${apiGet}
const getPai = `${list}/roleassignments?$expand=Member/users,RoleDefinitionBindings`;
console.log("request", getPai);
const response = await fetch(getPai, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
});
const data = await response.json();
data.d.results;
console.log(data.d.results);
const ret = [];
for (let i = 0; i < data.d.results.length; i++) {
var perm = data.d.results[i];
const toAdd = {};
toAdd.ListId = Id;
toAdd.ListTitle = Title;
toAdd.ListServerRelativeUrl = ServerRelativeUrl;
toAdd.ItemsCount = ItemsCount;
toAdd.Hidden = Hidden;
toAdd.HasUniqueRoleAssignments = HasUniqueRoleAssignments;
toAdd.Id = perm.Member.Id;
toAdd.LoginName = perm.Member.LoginName;
toAdd.Email = perm.Member.Email ?? "";
toAdd.Description = perm.Member.Description;
toAdd.Title = perm.Member.Title;
toAdd.IsHiddenInUI = perm.Member.IsHiddenInUI;
toAdd.PrincipalId = perm.Member.PrincipalId;
toAdd.PrincipalType = perm.Member.PrincipalType;
//users bu group
if (perm.Member.Users !== undefined && perm.Member.Users !== null && perm.Member.Users.results.length > 0) {
toAdd.Users = [];
for (let j = 0; j < perm.Member.Users.results.length; j++) {
const u = perm.Member.Users.results[j];
toAdd.Users.push({
Email: u.Email,
Id: u.Id,
Title: u.Title,
UserPrincipalName: u.UserPrincipalName,
IsSiteAdmin: u.IsSiteAdmin,
IsShareByEmailGuestUser: u.IsShareByEmailGuestUser
});
}
}
toAdd.RoleDefinitionBindings = ""
if (perm.RoleDefinitionBindings !== undefined && perm.RoleDefinitionBindings !== null && perm.RoleDefinitionBindings.results.length > 0) {
for (let j = 0; j < 1; j++) {
const r = perm.RoleDefinitionBindings.results[j];
toAdd.RoleDefinitionBindings = r.Name;
}
}
ret.push(toAdd);
}
console.log(ret);
return ret;
}
let url = "https://test.sharepoint.com/sites/csc";
let lists = `${url}/_api/web/lists?$select=Hidden,Title,RootFolder/ServerRelativeUrl,Id,ItemCount,HasUniqueRoleAssignments&$expand=RootFolder`;//&$filter=Hidden eq false
let response = await fetch(lists, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
});
let data = await response.json();
let datas = [];
for (let z = 0; z < data.d.results.length; z++) {//
const lst = data.d.results[z];
console.log("lst", lst);
const datas1 = await getRoleDefinitionBindings(`${url}/_api/web/lists(guid'${lst.Id}')`, lst.Id, lst.Title, lst.RootFolder.ServerRelativeUrl, lst.ItemCount, lst.Hidden, lst.HasUniqueRoleAssignments);
console.log(datas1);
for (let u = 0; u < datas1.length; u++) {
datas.push(datas1[u]);
}
}
console.log("datas", datas);
let csv = "ListId;ListTitle;ListServerRelativeUrl;ItemsCount;Hidden;HasUniqueRoleAssignments;MemberTitle;MemberEmail;MemberLoginName;MemberId;MemberDescription;Permission;TopLevel;UserMail;UserTitle;UserId;UserUserPrincipalName;IsSiteAdmin;IsShareByEmailGuestUser\n";
for (let k = 0; k < datas.length; k++) {
const d = datas[k];
let member = "";
member += `${d.ListId};`
member += `${d.ListTitle};`
member += `${d.ListServerRelativeUrl};`
member += `${d.ItemsCount};`
member += `${d.Hidden};`
member += `${d.HasUniqueRoleAssignments};`
member += `${d.Title};`
member += `${d.Email};`
member += `${d.LoginName};`
member += `${d.Id};`
member += `${d.Description ?? ""};`
member += `${d.RoleDefinitionBindings};`
csv += `${member}true;;;;;;\n`;
//debugger;
if (d.Users !== undefined) {
for (let j = 0; j < d.Users.length; j++) {
const user = d.Users[j];
let u = `${member}false;`;
u += `${user.Email};`;
u += `${user.Title};`;
u += `${user.Id};`;
u += `${user.UserPrincipalName ?? ""};`;
u += `${user.IsSiteAdmin};`;
u += `${user.IsShareByEmailGuestUser}`;
csv += `${u}\n`
}
}
}
console.log(csv);
Get Web Role Assignments
On 27/05/2025
// Fonction pour récupérer tous les RoleDefinitionBindings
async function getRoleDefinitionBindings(apiGet, type) {
let p = `vdfvd`;//$${apiGet}
const getPai = `${apiGet}/roleassignments?$expand=Member/users,RoleDefinitionBindings`;
const response = await fetch(getPai, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose'
}
});
const data = await response.json();
data.d.results;
console.log(data.d.results);
const ret = [];
for (let i = 0; i < data.d.results.length; i++) {
var perm = data.d.results[i];
const toAdd = {};
toAdd.type = type;
toAdd.Id = perm.Member.Id;
toAdd.LoginName = perm.Member.LoginName;
toAdd.Email = perm.Member.Email ?? "";
toAdd.Description = perm.Member.Description;
toAdd.Title = perm.Member.Title;
toAdd.IsHiddenInUI = perm.Member.IsHiddenInUI;
toAdd.PrincipalId = perm.Member.PrincipalId;
toAdd.PrincipalType = perm.Member.PrincipalType;
//users bu group
if (perm.Member.Users !== undefined && perm.Member.Users !== null && perm.Member.Users.results.length > 0) {
toAdd.Users = [];
for (let j = 0; j < perm.Member.Users.results.length; j++) {
const u = perm.Member.Users.results[j];
toAdd.Users.push({
Email: u.Email,
Id: u.Id,
Title: u.Title,
UserPrincipalName: u.UserPrincipalName,
IsSiteAdmin: u.IsSiteAdmin,
IsShareByEmailGuestUser: u.IsShareByEmailGuestUser
});
}
}
//debugger;
// = [];
toAdd.RoleDefinitionBindings = ""
if (perm.RoleDefinitionBindings !== undefined && perm.RoleDefinitionBindings !== null && perm.RoleDefinitionBindings.results.length > 0) {
for (let j = 0; j < 1; j++) {
const r = perm.RoleDefinitionBindings.results[j];
toAdd.RoleDefinitionBindings = r.Name;
// toAdd.RoleDefinitionBindings = {
// Name: r.Name,
// Hidden: r.Hidden,
// Description: r.Description,
// RoleTypeKind: r.RoleTypeKind,
// Order: r.Order
// };
}
}
ret.push(toAdd);
}
console.dir("ret", ret);
console.log(ret);
return ret;
}
let url = "https://test.sharepoint.com/sites/csc";
debugger;
const datas = await getRoleDefinitionBindings(`${url}/_api/web`, "SiteCollection");
let csv = "type;MemberTitle;MemberEmail;MemberLoginName;MemberId;MemberDescription;Permission;TopLevel;UserMail;UserTitle;UserId;UserUserPrincipalName;IsSiteAdmin;IsShareByEmailGuestUser\n";
for (let k = 0; k < datas.length; k++) {
const d = datas[k];
let member = "";
member += `${d.type};`
member += `${d.Title};`
member += `${d.Email};`
member += `${d.LoginName};`
member += `${d.Id};`
member += `${d.Description ?? ""};`
member += `${d.RoleDefinitionBindings};`
csv += `${member}true;;;;;;\n`;
//debugger;
if (d.Users !== undefined) {
for (let j = 0; j < d.Users.length; j++) {
const user = d.Users[j];
let u = `${member}false;`;
u += `${user.Email};`;
u += `${user.Title};`;
u += `${user.Id};`;
u += `${user.UserPrincipalName ?? ""};`;
u += `${user.IsSiteAdmin};`;
u += `${user.IsShareByEmailGuestUser}`;
csv += `${u}\n`
}
}
}
console.log(csv);
PowerShell Compaire Property Items
On 26/05/2025
$ret1 = "PO-REQ-..2101.docx" # $ret2 = "PO-RE..-2101.pdf" $url1 = "https://test.sharepoint.com/sites/test/procedures"; $url2 = "https://test.sharepoint.com/sites/test/procedures" Clear-Host function ToPdf { param($fileName) $paths = $fileName.Split(".") if ($paths.Count -eq 2) { return "$($paths[0]).pdf" } if ($paths.Count -gt 2) { $ret = ""; for ($i = 0 ; $i -lt $paths.Count - 1 ; $i++) { $ret += "$($paths[$i])" + "." } $ret += "pdf" return $ret } throw "Error : $($fileName)" } $list = "Work Instructions - Sources" $list2 = "Work Instructions" $ColumnsToCompaire = "Csc_Domain" $ColumnRef = "" $select = "Title,FileLeafRef,Csc_Domain,FileDirRef" $buildSelet = "<View Scope='RecursiveAll'><RowLimit>1000</RowLimit><OrderBy><FieldRef Name='Modified' Ascending='FALSE' /></OrderBy><Query><Where><Neq><FieldRef Name='FSObjType' /><Value Type='Integer'>1</Value></Neq></Where></Query>$($select)</View>" foreach ($col in ($select -split ",")) { $buildSelet += " " $con1 = Connect-PnPOnline -Url $url1 -ReturnConnection -UseWebLogin $con2 = Connect-PnPOnline -Url $url2 -ReturnConnection -UseWebLogin $list1 = Get-PnPList -Identity $list -Connection $con1 Write-Host "list 1 : $($list1.ItemCount)" $query = "" } $buildSelet += " " $items1 = Get-PnPListItem -List $list -Connection $con1 -Query $query $items2 = Get-PnPListItem -List $list2 -Connection $con2 -Query $query foreach ($item in $items1) { if ("$($item[$ColumnsToCompaire] )".Trim().ToLower() -eq "") { continue; } Write-Host "" Write-Host "list 1 : $($list1.ItemCount) item $($item.Id) ------------------" foreach ($col in ($select -split ",")) { Write-Host "item $($item.Id) '$($col)' : '$($item[$col])'" "item 1 $($item.Id) '$($col)' : '$($item[$col])'" | Out-File -LiteralPath ".\log\myLog_1.txt" -Encoding utf8 -Append } #$found = $items2 | Where-Object {$_.FileLeafRef -eq $item["FileLeafRef"]} #) -and $_.FileDirRef -eq $item["FileDirRef"] $founds = @(); $toFound = ToPdf -fileName $item["FileLeafRef"] foreach ($found in $items2) { if ("$($toFound)".Trim().ToLower() -eq "$($found["FileLeafRef"])".Trim().ToLower()) { $founds += $found } } if ($null -eq $founds) { Write-Error "File Error : $($item["FileLeafRef"]))" -ForegroundColor Yellow } elseif ($founds.Count -eq 0) { Write-Host "File ne found $($($item["FileLeafRef"])) -> $($toFound)" -ForegroundColor Yellow "File ne found $($($item["FileLeafRef"])) -> $($toFound)" | Out-File -LiteralPath ".\log\myLog_NotFound.txt" -Encoding utf8 -Append } elseif ($founds.Count -gt 1) { Write-Error "More than 1 file" } elseif ($founds.Count -eq 1) { if ($item[$ColumnsToCompaire] -ne $founds[0][$ColumnsToCompaire]) { Write-Host "to update" "to update $($item.Id) '$($toFound)' - origine : '$($item[$ColumnsToCompaire])' - pdf : '$($founds[0][$ColumnsToCompaire])'" | Out-File -LiteralPath ".\log\myLog_2.txt" -Encoding utf8 -Append Set-PnPListItem -UpdateType SystemUpdate -Identity $founds[0].Id -Connection $con2 -List $list2 -Values @{$ColumnsToCompaire = $item[$ColumnsToCompaire] } Write-Host "updated" } } }
Sharepoint Rest Compaire 2 Lists Fields
On 25/03/2025
// Fonction pour comparer les champs de deux listes SharePoint
async function compareSharePointLists(urlSite1, urlSite2, ListRelativeUrl1, ListRelativeUrl2) {
// Fonction auxiliaire pour obtenir les champs de la liste
async function getListFields(urlSite, ListRelativeUrl) {
const response = await fetch(`${urlSite}/_api/web/lists/getbytitle('${ListRelativeUrl}')/fields?$select=InternalName,TypeAsString`, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose',
},
});
if (!response.ok) {
throw new Error(`Error fetching fields for list at ${ListRelativeUrl}: ${response.statusText}`);
}
const data = await response.json();
return data.d.results;
}
try {
// Obtenir les champs des deux listes
const fields1 = await getListFields(urlSite1, ListRelativeUrl1);
const fields2 = await getListFields(urlSite2, ListRelativeUrl2);
// Comparer les champs
fields1.forEach(field1 => {
const matchingField = fields2.find(field2 => field2.InternalName === field1.InternalName);
if (!matchingField) {
console.log(`Le champ ${field1.InternalName} est manquant dans ${ListRelativeUrl2} de ${urlSite2}`);
} else if (field1.TypeAsString !== matchingField.TypeAsString) {
console.log(`Le type de champ ${field1.InternalName} ne correspond pas dans ${ListRelativeUrl2} de ${urlSite2} : ${field1.TypeAsString} vs ${matchingField.TypeAsString}`);
}
});
fields2.forEach(field2 => {
const matchingField = fields1.find(field1 => field1.InternalName === field2.InternalName);
if (!matchingField) {
console.log(`Le champ ${field2.InternalName} type ${field2.TypeAsString} est manquant dans ${ListRelativeUrl1} de ${urlSite1}`);
}
});
} catch (error) {
console.error('Erreur lors de la comparaison des champs des listes :', error);
}
}
// Example usage
compareSharePointLists(
'https://test.sharepoint.com/sites/DoceboMigration',
'https://test2.sharepoint.com/sites/fdiSandBox',
'testConfiguration',
'fdiTasks');
Sharepoint List Groups And Permissions
On 24/03/2025
// Function to list all SharePoint groups of a site collection with their permission levels
async function listSharePointGroupsWithPermissions(siteUrl, targetDivId) {
// Check if the siteUrl and targetDivId are provided
if (!siteUrl || !targetDivId) {
console.error("Site URL and target div ID must be provided.");
// L'URL du site et l'ID de la div cible doivent être fournis.
return;
}
// Construct the REST API URL to get the groups
const groupsEndpoint = `${siteUrl}/_api/web/sitegroups`;
try {
// Fetch the groups from the SharePoint site
const groupsResponse = await fetch(groupsEndpoint, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose',
},
});
// Check if the response is ok
if (!groupsResponse.ok) {
throw new Error(`Error fetching groups: ${groupsResponse.statusText}`);
// Erreur lors de la récupération des groupes :
}
// Parse the JSON response
const groupsData = await groupsResponse.json();
const groups = groupsData.d.results;
// Get the target div element
const targetDiv = document.getElementById(targetDivId);
if (!targetDiv) {
throw new Error(`Target div with ID ${targetDivId} not found.`);
// Div cible avec l'ID introuvable.
}
// Clear the target div
targetDiv.innerHTML = '';
const permsEndpoint = `${siteUrl}/_api/web/roleassignments?$expand=Member/users,RoleDefinitionBindings`;
const permsResponse = await fetch(permsEndpoint, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose',
},
})
const permsData = await permsResponse.json();
const roleAssignments = permsData.d.results;
if (!permsResponse.ok) {
throw new Error(`Error fetching roleassignments ${group.Title}: ${permsResponse.statusText}`);
// Erreur lors de la récupération des utilisateurs pour le groupe
}
// Iterate through each group and display its information
for (const group of groups) {
// Fetch the role assignments for the group
// Fetch the users in the group
const usersEndpoint = `${siteUrl}/_api/web/sitegroups(${group.Id})/users`;
const usersResponse = await fetch(usersEndpoint, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose',
},
});
// Check if the response is ok
if (!usersResponse.ok) {
throw new Error(`Error fetching users for group ${group.Title}: ${usersResponse.statusText}`);
// Erreur lors de la récupération des utilisateurs pour le groupe
}
// Parse the JSON response
const usersData = await usersResponse.json();
const users = usersData.d.results;
// Create a div for the group
const groupDiv = document.createElement('div');
groupDiv.className = 'group';
console.log(group.Title);
// Create a header for the group
const groupHeader = document.createElement('h3');
groupHeader.textContent = `Group: ${group.Title}`;
// Groupe :
groupDiv.appendChild(groupHeader);
// Create a list for the permission levels
console.log("permissionsList", roleAssignments, group);
const permissionsList = document.createElement('ul');
roleAssignments.forEach(roleAssignment => {
if(roleAssignment.PrincipalId == group.Id){
//Description Name
roleAssignment.RoleDefinitionBindings.results.forEach(RoleDefinitionBinding => {
//RoleDefinitionBindings.results
const permissionItem = document.createElement('li');
permissionItem.textContent = `Permission Level: '${RoleDefinitionBinding.Name}' ${RoleDefinitionBinding.Description}`;
// Niveau de permission :
permissionsList.appendChild(permissionItem);
});
}
});
groupDiv.appendChild(permissionsList);
// Create a list for the users in the group
const usersList = document.createElement('ul');
users.forEach(user => {
const userItem = document.createElement('li');
userItem.textContent = `User: ${user.Title}`;
// Utilisateur :
usersList.appendChild(userItem);
});
groupDiv.appendChild(usersList);
// Append the group div to the target div
targetDiv.appendChild(groupDiv);
}
} catch (error) {
// Log the error to the console
console.error(`Error: ${error.message}`);
// Erreur :
// Optionally, display the error message in the target div
const targetDiv = document.getElementById(targetDivId);
if (targetDiv) {
targetDiv.innerHTML = `
Error: ${error.message}
`; //
Erreur : } } } // Example usage await listSharePointGroupsWithPermissions('https://test.sharepoint.com/sites/ssss', 'vpc_WebPart.unknown.a90bc6dc-fba2-4b5c-b7e2-f72005f01a14');
Sharepoint json formatting status icons
On 18/03/2025
![]()
Here are the CSS classes used in JSON column formatting as sp-field-severity: sp-field-severity--low: This class is used to indicate a low severity level. It typically applies a specific style to represent low urgency or importance1234. sp-field-severity--good: This class is used to indicate a good or positive status. It applies a style that signifies a favorable condition1234. sp-field-severity--warning: This class is used to indicate a warning level. It applies a style that signifies caution or a moderate level of urgency1234. sp-field-severity--severeWarning: This class is used to indicate a severe warning level. It applies a style that signifies a high level of urgency or importance12354. sp-field-severity--blocked: This class is used to indicate a blocked or critical status. It applies a style that signifies a very high level of urgency or a critical issue12354. These classes are part of the SharePoint framework and are used to apply consistent styling across different columns based on the severity or status of the data. { "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json", "elmType": "div", "attributes": { "class": "=if(@currentField == 'CheckMark', 'sp-field-severity--good', if(@currentField == 'Completed', 'sp-field-severity--good', if(@currentField == 'Forward', 'sp-field-severity--low', if(@currentField == 'Warning', 'sp-field-severity--warning', if(@currentField == 'Error', 'sp-field-severity--severeWarning', if(@currentField == 'ErrorBadge', 'sp-field-severity--blocked', '')))))) + ' ms-fontColor-neutralSecondary'" }, "children": [ { "elmType": "span", "style": { "display": "inline-block", "padding": "0 4px" }, "attributes": { "iconName": "@currentField" } }, { "elmType": "span", "txtContent": "@currentField" } ] } CheckMark Completed Error Warning Forward ErrorBadge Add AddFriend Admin Airplane Alert AlignCenter AlignLeft AlignRight Archive ArrowDown ArrowLeft ArrowRight ArrowUp Attach Back Blocked Bold Bookmark Calendar Camera Cancel Checkbox CheckboxComposite CheckboxIndeterminate Checkmark ChevronDown ChevronLeft ChevronRight ChevronUp CircleRing Clear Clock Close Cloud Code CollapseMenu Color Comment Contact Copy CreditCard DataUsage Delete Dismiss Document Edit Education Emoji Error ErrorBadge Event Favorite Filter Flag Folder Forward Gift Globe Group Help History Home Important Info Italic Link List Location Lock Mail Map Megaphone Mention Message More Music NavigateBack NavigateForward News Note Open Paste Pause People Phone Photo Pin Play Print Product Redo Refresh Remove Reply Save Search Send Settings Share Shop ShoppingCart SignOut Sort Star Status Story Tag Task Trash Undo Unlock Upload User Video View Warning Work
PowerShell SharePoint Search Extract File Content
On 12/03/2025
# Parameters
$siteUrl = "https://xxxx.sharepoint.com/sites/xxxx"
$outputFilePath = "report4.txt"
$doclibpath = "/Connectivity"
# Connect to the SharePoint site
Connect-PnPOnline -Url $siteUrl -UseWebLogin
# Initialize the output file
if (Test-Path $outputFilePath) {
Remove-Item $outputFilePath
}
New-Item -Path $outputFilePath -ItemType File
# Define the search query to find '.url' files
$query = "Path:$($siteUrl)* And FileExtension:url"
$query = "Path:$($siteUrl)$($doclibpath)* And *.url"
# Execute the search query
$searchResults = Submit-PnPSearchQuery -Query $query -ErrorAction Stop -All -TrimDuplicates $true -SelectProperties "Path,FileName"
Write-Host "nb files found $($searchResults.TotalRows)"
# Check if there are any search results
if ($null -eq $searchResults -or $searchResults.TotalRows -eq 0) {
Write-Host "No '.url' files found in the search results."
Exit
}
# Initialize a variable to store combined content
$combinedContent = ""
$count = 0;
# Iterate through each search result
foreach ($result in $searchResults.ResultRows) {# ResultRows PrimarySearchResults
# Get the file URL
$fileUrl = $result.Path
if(-not $result.Path.ToLower().EndsWith(".url")){
continue;
}
$count++;
# Get the file content
$fileContent = $null;
# $fileContent = Get-PnPFileContent -Url $fileUrl -AsString -ErrorAction Stop
try {
$fileContent = Get-PnPFile -Url $fileUrl.Replace("https://eutelsatgroup.sharepoint.com", "") -AsString
}
catch {
Write-Host "File '$($fileUrl)' error. $($_)"
continue;
}
#$fileContent = Get-PnPFile -Url $fileUrl -AsString
# Check if the file content is null or empty
if ([string]::IsNullOrEmpty($fileContent)) {
Write-Host "File '$fileUrl' is empty or null."
continue
}
# Append the file content to the combined content
$combinedContent += $result.FileName + "`n"
$combinedContent += $fileUrl + "`n"
$combinedContent += $fileContent + "`n`n"
}
# Write the combined content to the output file
Add-Content -Path $outputFilePath -Value $combinedContent
# Disconnect from SharePoint Online
Disconnect-PnPOnline
Write-Host "nb files treated: $($count) Combined content written to '$($outputFilePath)'."
Fluent Ui Componants List
On 25/02/2025
Fluent UI Components and Properties
Button
| Property | Description |
|---|---|
| text | The text to display on the button. |
| iconProps | Properties to pass to the icon. |
| onClick | Callback for when the button is clicked. |
| disabled | Whether the button is disabled. |
TextField
| Property | Description |
|---|---|
| label | The label for the text field. |
| value | The value of the text field. |
| onChange | Callback for when the value changes. |
| placeholder | Placeholder text for the text field. |
| disabled | Whether the text field is disabled. |
Dropdown
| Property | Description |
|---|---|
| label | The label for the dropdown. |
| options | Array of options to display in the dropdown. |
| selectedKey | The key of the selected option. |
| onChange | Callback for when the selected option changes. |
| placeholder | Placeholder text for the dropdown. |
| disabled | Whether the dropdown is disabled. |
Checkbox
| Property | Description |
|---|---|
| label | The label for the checkbox. |
| checked | Whether the checkbox is checked. |
| onChange | Callback for when the checkbox is toggled. |
| disabled | Whether the checkbox is disabled. |
Toggle
| Property | Description |
|---|---|
| label | The label for the toggle. |
| checked | Whether the toggle is checked. |
| onChange | Callback for when the toggle is toggled. |
| disabled | Whether the toggle is disabled. |
Modal
| Property | Description |
|---|---|
| isOpen | Whether the modal is open. |
| onDismiss | Callback for when the modal is dismissed. |
| isBlocking | Whether the modal is blocking. |
| containerClassName | Custom class name for the modal container. |
Panel
| Property | Description |
|---|---|
| isOpen | Whether the panel is open. |
| onDismiss | Callback for when the panel is dismissed. |
| headerText | The text to display in the panel header. |
| closeButtonAriaLabel | The ARIA label for the close button. |
DetailsList
| Property | Description |
|---|---|
| items | Array of items to display in the list. |
| columns | Array of column definitions. |
| onItemInvoked | Callback for when an item is invoked. |
| selection | Selection object to manage selected items. |
Icon
| Property | Description |
|---|---|
| iconName | The name of the icon to display. |
| style | Custom styles for the icon. |
| className | Custom class name for the icon. |
Spinner
| Property | Description |
|---|---|
| label | The label for the spinner. |
| size | The size of the spinner (e.g., 'small', 'medium', 'large'). |
| ariaLive | The ARIA live region attribute. |
MessageBar
| Property | Description |
|---|---|
| messageBarType | The type of the message bar (e.g., 'info', 'success', 'warning', 'error'). |
| isMultiline | Whether the message bar should display multiple lines. |
| onDismiss | Callback for when the message bar is dismissed. |
| dismissButtonAriaLabel | The ARIA label for the dismiss button. |
Sharepoint List get list fields in console
On 20/02/2025
function getUrlParams() {
const params = new URLSearchParams(window.location.search);
const urlParams = {};
for (const [key, value] of params.entries()) {
urlParams[key] = value;
}
return urlParams;
}
async function getSharePointListFields(listId) {
const apiUrl = `${_spPageContextInfo.webAbsoluteUrl}/_api/web/lists(guid'${listId}')/fields?$select=InternalName&$orderby=InternalName&$filter=Hidden eq false`;
try {
const response = await fetch(apiUrl, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=verbose',
'Content-Type': 'application/json;odata=verbose',
},
credentials: 'include', // Include credentials for authenticated requests
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data.d.results;
} catch (error) {
console.error('Error fetching SharePoint list fields:', error);
return [];
}
}
// Usage
const urlParams = getUrlParams();
const listId = urlParams.List;
window.Fields = "";
if (listId) {
getSharePointListFields(listId).then((fields) => {
console.log('SharePoint List Fields:', fields);
// Process the fields as needed
fields.map((f) => {
window.Fields += `${f.InternalName}\n`;
});
console.log(window.Fields);
});
} else {
console.error('List ID not found in URL parameters');
}
SharePoint Sites.Selected
On 03/02/2025
How to give permission for an Azure app you has permission : Sites.Selected
You must be admin of Azure
In Graph Explorer use this request to get the Azure Id of you Site
Add for permission Sites.selected and Site.FullControl for the account (in modify permissions Tab)

https://graph.microsoft.com/v1.0/sites/m365x87466739.sharepoint.com:/sites/allcompany?$select=id
replace the m365x87466739 by your Tenant name, and allcompany by the name / url of your site,
it wiil returns you the azure id of your site
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites(id)/$entity",
"id": "m365x87466739.sharepoint.com,1dc83cb4-d304-4afa-a0ff-cf33270f1c8b,e615f00e-ac05-4dfc-928e-e51688e8273b"
}
Then post a news query https://graph.microsoft.com/v1.0/sites/m365x87466739.sharepoint.com,1dc83cb4-d304-4afa-a0ff-cf33270f1c8b,e615f00e-ac05-4dfc-928e-e51688e8273b/permissions
{
"roles": ["write"],//permission level you want to give
"grantedToIdentities": [{
"application": {
"id": "9fb5c53a-5f25-4100-ba33-9a4595390c27",//this is you App Id
"displayName": "AppSharePointDocebo"
}
}]
}
then you can use Connect-PnPOnline -Url $siteUrl -ClientId $clientId -Thumbprint $thumbprint -Tenant $tenantId

You can use site.url /_layouts/15/appinv.aspx opage, but you must be site coll Admin, and admin SharePoint on Azure
<AppPermissionRequests AllowAppOnlyPolicy="true">
<AppPermissionRequest Scope="https://myTrenant.sharepoint.com/sites/sites/site1" Right="FullControl" />
</AppPermissionRequests>
Fileshare Migration to SharePoint
On 07/01/2025
Use SharePoint Migration Tool to upload your folder in a document library, here base settings in a json file
{
"Tasks": [
{
"SourcePath": "\\\\mySite.fr\\divisions\\Processed matrices\\Doc1",
"TargetPath": "https://test.sharepoint.com/sites/test1",
"TargetList": "FDbase",
"TargetListRelativePath": "Satellites/Doc1",
"Options": {
"PreserveFileSharePermissions": false,
"MigrateHiddenFiles": true,
"MigrateReadOnlyFiles": true,
"PreserveLastModifiedTime": true,
"PreserveCreatedTime": true,
"SkipEmptyFolders": false
}
}
]
}