Transelate table values, better automation - MS365 SKU pr company in tenant - Powershell - azure

Intro
Hi. so i have a script to check SKUs pr company within the same tenant. because sometimes there might be multiple companies sharing the same tenant, but maybe they want to get billed for licenses separately.
Right now my script works, but its not optimal.
first it does a check on the tenant. and then it promts the user for a company name after listing all companies within the tenant.
the user then writes a name from the list.
and you will get output like below
Skus for: Company Name
Count Name SKUName
----- ---- -------
1 f8a1db68-be16-40ed-86d5-cb42ce701560 POWER_BI_PRO
1 7ac9fe77-66b7-4e5e-9e46-10eed1cff547 DYN365_TEAM_MEMBERS
5 f30db892-07e9-47e9-837c-80727f46fd3d FLOW_FREE, FLOW_FREE, FLOW_FREE, FLOW_FREE, FLOW_FREE
21 4b9405b0-7788-4568-add1-99614e613b69 EXCHANGESTANDARD, EXCHANGESTANDARD, EXCHANGESTANDARD, EXCHANGESTANDARD, EXCHANGESTANDARD, EXCHANGESTANDARD, EXCHANGESTANDARD, EXCHANGESTANDARD, EXCHANGESTAN...
18 f245ecc8-75af-4f8e-b61f-27d8114de5f3 O365_BUSINESS_PREMIUM, O365_BUSINESS_PREMIUM, O365_BUSINESS_PREMIUM, O365_BUSINESS_PREMIUM, O365_BUSINESS_PREMIUM, O365_BUSINESS_PREMIUM, O365_BUSINESS_PREM...
3 a403ebcc-fae0-4ca2-8c8c-7a907fd6c235 POWER_BI_STANDARD, POWER_BI_STANDARD, POWER_BI_STANDARD
5 710779e8-3d4a-4c88-adb9-386c958d1fdf TEAMS_EXPLORATORY, TEAMS_EXPLORATORY, TEAMS_EXPLORATORY, TEAMS_EXPLORATORY, TEAMS_EXPLORATORY
6 3b555118-da6a-4418-894f-7df1e2096870 O365_BUSINESS_ESSENTIALS, O365_BUSINESS_ESSENTIALS, O365_BUSINESS_ESSENTIALS, O365_BUSINESS_ESSENTIALS, O365_BUSINESS_ESSENTIALS, O365_BUSINESS_ESSENTIALS
2 1e1a282c-9c54-43a2-9310-98ef728faace DYN365_ENTERPRISE_SALES, DYN365_ENTERPRISE_SALES
What i hope to fix
I would like to transelate the SKU names like below somehow. but im unsure about how to impliment this into the script. i would also love for the SKUName to only show once . not like the output above where it shows up as many times as the company have the sku.
i would also love it if it was possible to maybe make a loop that just printed out a table pr company in the tenant. instead of me having to write the names one by one in a prompt.
(script at the bottom of the question)
$LicenseLookup = #{
'SPZA_IW' = 'App Connect Iw'
'AAD_BASIC' = 'Azure Active Directory Basic'
'AAD_PREMIUM' = 'Azure Active Directory Premium P1'
'AAD_PREMIUM_P2' = 'Azure Active Directory Premium P2'
'RIGHTSMANAGEMENT' = 'Azure Information Protection Plan 1'
'MCOCAP' = 'Common Area Phone'
'MCOPSTNC' = 'Communications Credits'
'DYN365_ENTERPRISE_PLAN1' = 'Dynamics 365 Customer Engagement Plan Enterprise Edition'
'DYN365_ENTERPRISE_CUSTOMER_SERVICE' = 'Dynamics 365 For Customer Service Enterprise Edition'
'DYN365_FINANCIALS_BUSINESS_SKU' = 'Dynamics 365 For Financials Business Edition'
'DYN365_ENTERPRISE_SALES_CUSTOMERSERVICE' = 'Dynamics 365 For Sales And Customer Service Enterprise Edition'
'DYN365_ENTERPRISE_SALES' = 'Dynamics 365 For Sales Enterprise Edition'
'DYN365_ENTERPRISE_TEAM_MEMBERS' = 'Dynamics 365 For Team Members Enterprise Edition'
'DYN365_TEAM_MEMBERS' = 'Dynamics 365 Team Members'
'Dynamics_365_for_Operations' = 'Dynamics 365 Unf Ops Plan Ent Edition'
'EMS' = 'Enterprise Mobility + Security E3'
'EMSPREMIUM' = 'Enterprise Mobility + Security E5'
'EXCHANGESTANDARD' = 'Exchange Online (Plan 1)'
'EXCHANGEENTERPRISE' = 'Exchange Online (Plan 2)'
'EXCHANGEARCHIVE_ADDON' = 'Exchange Online Archiving For Exchange Online'
'EXCHANGEARCHIVE' = 'Exchange Online Archiving For Exchange Server'
'EXCHANGEESSENTIALS' = 'Exchange Online Essentials'
'EXCHANGE_S_ESSENTIALS' = 'Exchange Online Essentials'
'EXCHANGEDESKLESS' = 'Exchange Online Kiosk'
'EXCHANGETELCO' = 'Exchange Online Pop'
'INTUNE_A' = 'Intune'
'M365EDU_A1' = 'Microsoft 365 A1'
'M365EDU_A3_FACULTY' = 'Microsoft 365 A3 For Faculty'
'M365EDU_A3_STUDENT' = 'Microsoft 365 A3 For Students'
'M365EDU_A5_FACULTY' = 'Microsoft 365 A5 For Faculty'
'M365EDU_A5_STUDENT' = 'Microsoft 365 A5 For Students'
'O365_BUSINESS' = 'Microsoft 365 Apps For Business'
'SMB_BUSINESS' = 'Microsoft 365 Apps For Business'
'OFFICESUBSCRIPTION' = 'Microsoft 365 Apps For Enterprise'
'MCOMEETADV' = 'Microsoft 365 Audio Conferencing'
'MCOMEETADV_GOC' = 'Microsoft 365 Audio Conferencing For Gcc'
'O365_BUSINESS_ESSENTIALS' = 'Microsoft 365 Business Basic'
'SMB_BUSINESS_ESSENTIALS' = 'Microsoft 365 Business Basic'
'SPB' = 'Microsoft 365 Business Premium'
'O365_BUSINESS_PREMIUM' = 'Microsoft 365 Business Standard'
'SMB_BUSINESS_PREMIUM' = 'Microsoft 365 Business Standard'
'MCOPSTN_5' = 'Microsoft 365 Domestic Calling Plan (120 Minutes)'
'SPE_E3' = 'Microsoft 365 E3'
'SPE_E3_USGOV_DOD' = 'Microsoft 365 E3_Usgov_Dod'
'SPE_E3_USGOV_GCCHIGH' = 'Microsoft 365 E3_Usgov_Gcchigh'
'SPE_E5' = 'Microsoft 365 E5'
'INFORMATION_PROTECTION_COMPLIANCE' = 'Microsoft 365 E5 Compliance'
'IDENTITY_THREAT_PROTECTION' = 'Microsoft 365 E5 Security'
'IDENTITY_THREAT_PROTECTION_FOR_EMS_E5' = 'Microsoft 365 E5 Security For Ems E5'
'M365_F1' = 'Microsoft 365 F1'
'SPE_F1' = 'Microsoft 365 F3'
'M365_G3_GOV' = 'Microsoft 365 Gcc G3'
'MCOEV' = 'Microsoft 365 Phone System'
'PHONESYSTEM_VIRTUALUSER' = 'Microsoft 365 Phone System - Virtual User'
'MCOEV_DOD' = 'Microsoft 365 Phone System For Dod'
'MCOEV_FACULTY' = 'Microsoft 365 Phone System For Faculty'
'MCOEV_GOV' = 'Microsoft 365 Phone System For Gcc'
'MCOEV_GCCHIGH' = 'Microsoft 365 Phone System For Gcchigh'
'MCOEVSMB_1' = 'Microsoft 365 Phone System For Small And Medium Business'
'MCOEV_STUDENT' = 'Microsoft 365 Phone System For Students'
'MCOEV_TELSTRA' = 'Microsoft 365 Phone System For Telstra'
'MCOEV_USGOV_DOD' = 'Microsoft 365 Phone System_Usgov_Dod'
'MCOEV_USGOV_GCCHIGH' = 'Microsoft 365 Phone System_Usgov_Gcchigh'
'WIN_DEF_ATP' = 'Microsoft Defender Advanced Threat Protection'
'CRMSTANDARD' = 'Microsoft Dynamics Crm Online'
'CRMPLAN2' = 'Microsoft Dynamics Crm Online Basic'
'FLOW_FREE' = 'Microsoft Flow Free'
'INTUNE_A_D_GOV' = 'Microsoft Intune Device For Government'
'POWERAPPS_VIRAL' = 'Microsoft Power Apps Plan 2 Trial'
'TEAMS_FREE' = 'Microsoft Team (Free)'
'TEAMS_EXPLORATORY' = 'Microsoft Teams Exploratory'
'IT_ACADEMY_AD' = 'Ms Imagine Academy'
'ENTERPRISEPREMIUM_FACULTY' = 'Office 365 A5 For Faculty'
'ENTERPRISEPREMIUM_STUDENT' = 'Office 365 A5 For Students'
'EQUIVIO_ANALYTICS' = 'Office 365 Advanced Compliance'
'ATP_ENTERPRISE' = 'Microsoft Defender for Office 365 (Plan 1)'
'STANDARDPACK' = 'Office 365 E1'
'STANDARDWOFFPACK' = 'Office 365 E2'
'ENTERPRISEPACK' = 'Office 365 E3'
'DEVELOPERPACK' = 'Office 365 E3 Developer'
'ENTERPRISEPACK_USGOV_DOD' = 'Office 365 E3_Usgov_Dod'
'ENTERPRISEPACK_USGOV_GCCHIGH' = 'Office 365 E3_Usgov_Gcchigh'
'ENTERPRISEWITHSCAL' = 'Office 365 E4'
'ENTERPRISEPREMIUM' = 'Office 365 E5'
'ENTERPRISEPREMIUM_NOPSTNCONF' = 'Office 365 E5 Without Audio Conferencing'
'DESKLESSPACK' = 'Office 365 F3'
'ENTERPRISEPACK_GOV' = 'Office 365 Gcc G3'
'MIDSIZEPACK' = 'Office 365 Midsize Business'
'LITEPACK' = 'Office 365 Small Business'
'LITEPACK_P2' = 'Office 365 Small Business Premium'
'WACONEDRIVESTANDARD' = 'Onedrive For Business (Plan 1)'
'WACONEDRIVEENTERPRISE' = 'Onedrive For Business (Plan 2)'
'POWER_BI_STANDARD' = 'Power Bi (Free)'
'POWER_BI_ADDON' = 'Power Bi For Office 365 Add-On'
'POWER_BI_PRO' = 'Power Bi Pro'
'PROJECTCLIENT' = 'Project For Office 365'
'PROJECTESSENTIALS' = 'Project Online Essentials'
'PROJECTPREMIUM' = 'Project Online Premium'
'PROJECTONLINE_PLAN_1' = 'Project Online Premium Without Project Client'
'PROJECTPROFESSIONAL' = 'Microsoft Project Plan 3'
'PROJECTONLINE_PLAN_2' = 'Project Online With Project For Office 365'
'SHAREPOINTSTANDARD' = 'Sharepoint Online (Plan 1)'
'SHAREPOINTENTERPRISE' = 'Sharepoint Online (Plan 2)'
'MCOIMP' = 'Skype For Business Online (Plan 1)'
'MCOSTANDARD' = 'Skype For Business Online (Plan 2)'
'MCOPSTN2' = 'Skype For Business Pstn Domestic And International Calling'
'MCOPSTN1' = 'Skype For Business Pstn Domestic Calling'
'MCOPSTN5' = 'Skype For Business Pstn Domestic Calling (120 Minutes)'
'MCOPSTNEAU2' = 'Telstra Calling For O365'
'TOPIC_EXPERIENCES' = 'Topic Experiences'
'VISIOONLINE_PLAN1' = 'Visio Online Plan 1'
'VISIOCLIENT' = 'Visio Online Plan 2'
'VISIOCLIENT_GOV' = 'Visio Plan 2 For Gov'
'WIN10_PRO_ENT_SUB' = 'Windows 10 Enterprise E3'
'WIN10_VDA_E3' = 'Windows 10 Enterprise E3'
'WIN10_VDA_E5' = 'Windows 10 Enterprise E5'
'WINDOWS_STORE' = 'Windows Store For Business'
'RMSBASIC' = 'Azure Information Protection Basic'
'UNIVERSAL_PRINT_M365' = 'Universal Print'
'RIGHTSMANAGEMENT_ADHOC' = 'Rights Management Service Basic Content Protection'
'SKU_Dynamics_365_for_HCM_Trial' = 'Dynamics 365 for Talent'
'PROJECT_P1' = 'Project Plan 1'
'PROJECT_PLAN1_DEPT' = 'Project Plan 1 (Self Service)'
'SHAREPOINTSTORAGE' = 'Microsoft Office 365 Extra File Storage'
'NONPROFIT_PORTAL' = 'Non Profit Portal'
'MDE_SMB' = 'Microsoft Defender for Endpoint (Business Premium)'
}
The current script i use
below is the script as it is today. and how i use it. keep in mind that this is made by me (a noob). so some things might not make too much sense as to why i do things as i do.
any tips would be welcome.
cls
Connect-AzureAD
$Report = [System.Collections.Generic.List[Object]]::new() # Create output file
$Skus = Get-AzureADSubscribedSku | Select Sku*, ConsumedUnits
ForEach ($Sku in $Skus) {
Write-Host "Processing license holders for" $Sku.SkuPartNumber
$SkuUsers = Get-AzureADUser -All $True | ? { $_.AssignedLicenses -Match $Sku.SkuId }
ForEach ($User in $SkuUsers) {
$ReportLine = [PSCustomObject] #{
User = $User.DisplayName
UPN = $User.UserPrincipalName
Companyname = $User.Companyname
Country = $User.Country
SKU = $Sku.SkuId
SKUName = $Sku.SkuPartNumber
}
$Report.Add($ReportLine)
}
}
cls
$commands = {
#Collects all companies within the tenant
$companies = $Report | Select-Object Companyname -Unique
write-host "Below is a list of all Companies in the tenant";
$companies | Out-Host
$userinput = "FALSE"
$userinput = Read-Host "Write the name of the company you want to check:";
#just some padding
write-host " "
write-host " "
write-host " "
write-host " "
write-host "Skus for: $userinput" #adding a title based on what you write.
$Report | Where-Object Companyname -like $userinput | Group-Object -Property SKU | Select-Object Count, Name, #{Name = 'SKUName' ; expression = { ($_.Group.SKUName) -join ', ' } } | Format-Table
#prompts the user for another check.
$again = Read-Host "again?"
if ($again -eq "y"){
&$commands
} else {
Write-Host "exited..."
}
}
&$commands
Outro
I hope what i wrote was understandable. My enlish is not the best,so for that im sorry.
any help or tips regarding what i asked for woule be amazing. thanks!

the solution was as #mathisas R. Jenssen posted.
and then i just ran this with a very ugly loop throughout the list of companynames in the tenant.
below is the part of the script that changed. if you are running this you should run this with the $report and $skus foreach loop like before.
but below u add this:
$LicenseLookup = #{
'SPZA_IW' = 'App Connect Iw'
'AAD_BASIC' = 'Azure Active Directory Basic'
'AAD_PREMIUM' = 'Azure Active Directory Premium P1'
'AAD_PREMIUM_P2' = 'Azure Active Directory Premium P2'
'RIGHTSMANAGEMENT' = 'Azure Information Protection Plan 1'
'MCOCAP' = 'Common Area Phone'
'MCOPSTNC' = 'Communications Credits'
'DYN365_ENTERPRISE_PLAN1' = 'Dynamics 365 Customer Engagement Plan Enterprise Edition'
'DYN365_ENTERPRISE_CUSTOMER_SERVICE' = 'Dynamics 365 For Customer Service Enterprise Edition'
'DYN365_FINANCIALS_BUSINESS_SKU' = 'Dynamics 365 For Financials Business Edition'
'DYN365_ENTERPRISE_SALES_CUSTOMERSERVICE' = 'Dynamics 365 For Sales And Customer Service Enterprise Edition'
'DYN365_ENTERPRISE_SALES' = 'Dynamics 365 For Sales Enterprise Edition'
'DYN365_ENTERPRISE_TEAM_MEMBERS' = 'Dynamics 365 For Team Members Enterprise Edition'
'DYN365_TEAM_MEMBERS' = 'Dynamics 365 Team Members'
'Dynamics_365_for_Operations' = 'Dynamics 365 Unf Ops Plan Ent Edition'
'EMS' = 'Enterprise Mobility + Security E3'
'EMSPREMIUM' = 'Enterprise Mobility + Security E5'
'EXCHANGESTANDARD' = 'Exchange Online (Plan 1)'
'EXCHANGEENTERPRISE' = 'Exchange Online (Plan 2)'
'EXCHANGEARCHIVE_ADDON' = 'Exchange Online Archiving For Exchange Online'
'EXCHANGEARCHIVE' = 'Exchange Online Archiving For Exchange Server'
'EXCHANGEESSENTIALS' = 'Exchange Online Essentials'
'EXCHANGE_S_ESSENTIALS' = 'Exchange Online Essentials'
'EXCHANGEDESKLESS' = 'Exchange Online Kiosk'
'EXCHANGETELCO' = 'Exchange Online Pop'
'INTUNE_A' = 'Intune'
'M365EDU_A1' = 'Microsoft 365 A1'
'M365EDU_A3_FACULTY' = 'Microsoft 365 A3 For Faculty'
'M365EDU_A3_STUDENT' = 'Microsoft 365 A3 For Students'
'M365EDU_A5_FACULTY' = 'Microsoft 365 A5 For Faculty'
'M365EDU_A5_STUDENT' = 'Microsoft 365 A5 For Students'
'O365_BUSINESS' = 'Microsoft 365 Apps For Business'
'SMB_BUSINESS' = 'Microsoft 365 Apps For Business'
'OFFICESUBSCRIPTION' = 'Microsoft 365 Apps For Enterprise'
'MCOMEETADV' = 'Microsoft 365 Audio Conferencing'
'MCOMEETADV_GOC' = 'Microsoft 365 Audio Conferencing For Gcc'
'O365_BUSINESS_ESSENTIALS' = 'Microsoft 365 Business Basic'
'SMB_BUSINESS_ESSENTIALS' = 'Microsoft 365 Business Basic'
'SPB' = 'Microsoft 365 Business Premium'
'O365_BUSINESS_PREMIUM' = 'Microsoft 365 Business Standard'
'SMB_BUSINESS_PREMIUM' = 'Microsoft 365 Business Standard'
'MCOPSTN_5' = 'Microsoft 365 Domestic Calling Plan (120 Minutes)'
'SPE_E3' = 'Microsoft 365 E3'
'SPE_E3_USGOV_DOD' = 'Microsoft 365 E3_Usgov_Dod'
'SPE_E3_USGOV_GCCHIGH' = 'Microsoft 365 E3_Usgov_Gcchigh'
'SPE_E5' = 'Microsoft 365 E5'
'INFORMATION_PROTECTION_COMPLIANCE' = 'Microsoft 365 E5 Compliance'
'IDENTITY_THREAT_PROTECTION' = 'Microsoft 365 E5 Security'
'IDENTITY_THREAT_PROTECTION_FOR_EMS_E5' = 'Microsoft 365 E5 Security For Ems E5'
'M365_F1' = 'Microsoft 365 F1'
'SPE_F1' = 'Microsoft 365 F3'
'M365_G3_GOV' = 'Microsoft 365 Gcc G3'
'MCOEV' = 'Microsoft 365 Phone System'
'PHONESYSTEM_VIRTUALUSER' = 'Microsoft 365 Phone System - Virtual User'
'MCOEV_DOD' = 'Microsoft 365 Phone System For Dod'
'MCOEV_FACULTY' = 'Microsoft 365 Phone System For Faculty'
'MCOEV_GOV' = 'Microsoft 365 Phone System For Gcc'
'MCOEV_GCCHIGH' = 'Microsoft 365 Phone System For Gcchigh'
'MCOEVSMB_1' = 'Microsoft 365 Phone System For Small And Medium Business'
'MCOEV_STUDENT' = 'Microsoft 365 Phone System For Students'
'MCOEV_TELSTRA' = 'Microsoft 365 Phone System For Telstra'
'MCOEV_USGOV_DOD' = 'Microsoft 365 Phone System_Usgov_Dod'
'MCOEV_USGOV_GCCHIGH' = 'Microsoft 365 Phone System_Usgov_Gcchigh'
'WIN_DEF_ATP' = 'Microsoft Defender Advanced Threat Protection'
'CRMSTANDARD' = 'Microsoft Dynamics Crm Online'
'CRMPLAN2' = 'Microsoft Dynamics Crm Online Basic'
'FLOW_FREE' = 'Microsoft Flow Free'
'INTUNE_A_D_GOV' = 'Microsoft Intune Device For Government'
'POWERAPPS_VIRAL' = 'Microsoft Power Apps Plan 2 Trial'
'TEAMS_FREE' = 'Microsoft Team (Free)'
'TEAMS_EXPLORATORY' = 'Microsoft Teams Exploratory'
'IT_ACADEMY_AD' = 'Ms Imagine Academy'
'ENTERPRISEPREMIUM_FACULTY' = 'Office 365 A5 For Faculty'
'ENTERPRISEPREMIUM_STUDENT' = 'Office 365 A5 For Students'
'EQUIVIO_ANALYTICS' = 'Office 365 Advanced Compliance'
'ATP_ENTERPRISE' = 'Microsoft Defender for Office 365 (Plan 1)'
'STANDARDPACK' = 'Office 365 E1'
'STANDARDWOFFPACK' = 'Office 365 E2'
'ENTERPRISEPACK' = 'Office 365 E3'
'DEVELOPERPACK' = 'Office 365 E3 Developer'
'ENTERPRISEPACK_USGOV_DOD' = 'Office 365 E3_Usgov_Dod'
'ENTERPRISEPACK_USGOV_GCCHIGH' = 'Office 365 E3_Usgov_Gcchigh'
'ENTERPRISEWITHSCAL' = 'Office 365 E4'
'ENTERPRISEPREMIUM' = 'Office 365 E5'
'ENTERPRISEPREMIUM_NOPSTNCONF' = 'Office 365 E5 Without Audio Conferencing'
'DESKLESSPACK' = 'Office 365 F3'
'ENTERPRISEPACK_GOV' = 'Office 365 Gcc G3'
'MIDSIZEPACK' = 'Office 365 Midsize Business'
'LITEPACK' = 'Office 365 Small Business'
'LITEPACK_P2' = 'Office 365 Small Business Premium'
'WACONEDRIVESTANDARD' = 'Onedrive For Business (Plan 1)'
'WACONEDRIVEENTERPRISE' = 'Onedrive For Business (Plan 2)'
'POWER_BI_STANDARD' = 'Power Bi (Free)'
'POWER_BI_ADDON' = 'Power Bi For Office 365 Add-On'
'POWER_BI_PRO' = 'Power Bi Pro'
'PROJECTCLIENT' = 'Project For Office 365'
'PROJECTESSENTIALS' = 'Project Online Essentials'
'PROJECTPREMIUM' = 'Project Online Premium'
'PROJECTONLINE_PLAN_1' = 'Project Online Premium Without Project Client'
'PROJECTPROFESSIONAL' = 'Microsoft Project Plan 3'
'PROJECTONLINE_PLAN_2' = 'Project Online With Project For Office 365'
'SHAREPOINTSTANDARD' = 'Sharepoint Online (Plan 1)'
'SHAREPOINTENTERPRISE' = 'Sharepoint Online (Plan 2)'
'MCOIMP' = 'Skype For Business Online (Plan 1)'
'MCOSTANDARD' = 'Skype For Business Online (Plan 2)'
'MCOPSTN2' = 'Skype For Business Pstn Domestic And International Calling'
'MCOPSTN1' = 'Skype For Business Pstn Domestic Calling'
'MCOPSTN5' = 'Skype For Business Pstn Domestic Calling (120 Minutes)'
'MCOPSTNEAU2' = 'Telstra Calling For O365'
'TOPIC_EXPERIENCES' = 'Topic Experiences'
'VISIOONLINE_PLAN1' = 'Visio Online Plan 1'
'VISIOCLIENT' = 'Visio Online Plan 2'
'VISIOCLIENT_GOV' = 'Visio Plan 2 For Gov'
'WIN10_PRO_ENT_SUB' = 'Windows 10 Enterprise E3'
'WIN10_VDA_E3' = 'Windows 10 Enterprise E3'
'WIN10_VDA_E5' = 'Windows 10 Enterprise E5'
'WINDOWS_STORE' = 'Windows Store For Business'
'RMSBASIC' = 'Azure Information Protection Basic'
'UNIVERSAL_PRINT_M365' = 'Universal Print'
'RIGHTSMANAGEMENT_ADHOC' = 'Rights Management Service Basic Content Protection'
'SKU_Dynamics_365_for_HCM_Trial' = 'Dynamics 365 for Talent'
'PROJECT_P1' = 'Project Plan 1'
'PROJECT_PLAN1_DEPT' = 'Project Plan 1 (Self Service)'
'SHAREPOINTSTORAGE' = 'Microsoft Office 365 Extra File Storage'
'NONPROFIT_PORTAL' = 'Non Profit Portal'
'MDE_SMB' = 'Microsoft Defender for Endpoint (Business Premium)'
}
cls
#List of company names in the tenant
$Companies = $Report | Select-Object Companyname -Unique
#horrible improvised "for" loop that goes through the list of companynames
$counter = 0 #starting at pos [0]
foreach ($company in $Companies) {
#prints the current companyname
$Companies.companyname[$counter]
#formatting the table for the current companyname[i] where it shows count, name, and SKUName
$Report | Where-Object Companyname -like $Companies.companyname[$counter] | Group-Object -Property SKU | Select-Object Count, Name, #{Name = 'SKU Name' ; expression = { ($LicenseLookup[$_.Group.SKUName]) -join ', ' } } | Format-Table
#then moves down 1 pos in the current companyname[i]
$counter = $counter + 1
Write-Host "--------------------------------------------------------------------------------------------"
}

Related

Is there a way to add a new column in Sharepoint list that copies data from another column in that list?

I'm using Sharepoint Online.
I have a column in a list that is currently "Multiple lines of text".
If I try to use the SP UI and manually alter the Column Type to "Single Line of Text" I get "unsupportedFieldTypeError".
If I use Sharepoint Designer 2013, and access the list and try to click "Column Type" when I highlight this column, nothing happens.
I would really like to know if I can create a new column that is a "Single line of text" that just copies the value of this "Multiple lines of text" column?
Thanks!
You can create a new Single Line Text field and copy field value using PnP PowerShell below:
#Parameters
$SiteURL = "https://zheguo.sharepoint.com/"
$ListName = "JqueryList"
$SourceColumn = "MultiField" #Internal Name of the Fields
$DestinationColumn = "SingleField"
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credential Get-Credential
#Get all items from List
$ListItems = Get-PnPListItem -List $Listname
#Copy Values from one column to another
ForEach ($Item in $ListItems)
{
Set-PnPListItem -List $Listname -Identity $Item.Id -Values #{$DestinationColumn = $Item[$SourceColumn]}
}
Result:
Before using the PowerShell, please install PnP PowerShell here:
pnp/PnP-PowerShell
Reference:
SharePoint Online: Copy Values from One Column to Another using PowerShell

Sync Sharepoint with Office 2016

At our company we have a SharePoint 2013 installation.
Before when I was still running Office 2013 I could install the OneDrive for Business client which allowed me to sync my SharePoint Documents to my local PC.
I recently upgraded to Office 2016 and the installation of OneDrive for Business was deleted and replace with the "new" one drive. The new OneDrive allows sync with OneDrive for business but I can't find a way to sync with a SharePoint.
Does anyone know how to sync a SharePoint with a PC that runs Office 2016?
This question is more than a year old, but I just ran into the same problem, and found a workaround.
The specific issue I was facing was attempting to synchronize an Office 365 SharePoint shared document folder with the OneDrive client installed on my PC. When clicking the "Sync" button on a shared folder online, the browser would attempt to open the OneDrive for Business client. Clicking "Open OneDrive for Business" would launch the application and start synchronizing. After a minute or two, the client would then return "This library can no longer be synced using this application. To sync these files, use the latest OneDrive application."
Unsuccessful steps taken to solve the problem:
Uninstalling the newer OneDrive client
Removing the Office account and reauthenticating
Forcing OneDrive.exe (the new client) to open the "Sync" link
Copying the URL to the SharePoint folder, and manually adding it as a library to the OneDrive for Business Client
After some research and debugging, it seems that Microsoft has not yet updated SharePoint for Office 365 to use the newer protocol for the "next generation" OneDrive client. OneDrive for Business, formerly known as Groove, uses the Groove Open protocol (grvopen://) to interact with browser content. The new OneDrive client uses a different OneDrive Open protocol (odopen://).
A Groove Open link would look like this (line breaks added at & for readability):
grvopen://<url-encoded-path-to-library-here-including-https://>/{<SharePoint-list-id>}/<list-base-type>?OPENLIST&
siteId=<site-id>&
webId=<web-id>&
webTitle=<web-title>&
listId=<list-id-surrounded-by-braces>&
listTitle=<list-title>&
userEmail=<user-email>&
listTemplateTypeId=<list-base-template-id>&
webUrl=<url-encoded-absolute-path-to-folder>&
webLogoUrl=<relative-url-to-logo>&
webTemplate=<web-template>&
isSiteAdmin=<is-site-admin>
An example looks like this:
grvopen://https_58_47_47www_46sharepoint_46com_47Documents/_aahl00000000_450000_450000_450000_45000000000000%7D/101?OPENLIST&siteId=00000000-0000-0000-0000-000000000000&webId=00000000-0000-0000-0000-000000000000&webTitle=SharePoint%20Site%20Title&listId={00000000-0000-0000-0000-000000000000}&listTitle=Documents&userEmail=user#domain.com&listTemplateTypeId=101&webUrl=https%3A%2F%2Fwww.sharepoint.com%2FDocuments&webLogoUrl=_layouts%2F15%2Fimages%2Fsiteicon.png&webTemplate=1&isSiteAdmin=0
I'm not sure what kind of encoding results in the underscores with the URL, but it's irrelevant to the solution.
I was able to get my personal OneDrive directory in Office 365 to synchronize with the correct OneDrive client on my PC, so I used Chrome's Dev Tools to monitor network traffic when clicking "Sync". The traffic revealed the following URL format for the new OneDrive client (adding line breaks for readability):
odopen://sync?
siteId=<site-id>&
webId=<web-id>&
webTitle=<web-title>&
listId=<list-id-surrounded-by-braces>&
listTitle=<list-title>&
userEmail=<user-email>&
listTemplateTypeId=<list-base-template-id>&
webUrl=<url-encoded-absolute-path-to-folder>&
webLogoUrl=<relative-url-to-logo>&
webTemplate=<web-template>&
isSiteAdmin=<site-admin>&
scope=OPENLIST
And a sample URL:
odopen://sync?siteId=%7B00000000-0000-0000-0000-000000000000%7D&webId=%7B00000000-0000-0000-0000-000000000000%7D&webTitle=SharePoint%20Site%20Title&listId=%7B00000000-0000-0000-0000-000000000000%7D&listTitle=Documents&userEmail=email%40domain.com&listTemplateTypeId=101&webUrl=https%3A%2F%2Fwww.sharepoint.com%2FDocuments&webLogoUrl=_layouts%2F15%2Fimages%2Fsiteicon.png&webTemplate=1&isSiteAdmin=0&scope=OPENLIST
Not so different from the Groove links. To craft a correctly formatted OneDrive URL, I wrote a JavaScript bookmarklet to extract the necessary parameters from the global JavaScript variable _spPageContextInfo available in the DOM of a SharePoint site.
You may have noticed that the parameters containing Guids above are wrapped in curly braces. The Guids extracted from _spPageContextInfo are already wrapped in curly braces.
(function() {
var siteId = _spPageContextInfo.siteId
, webId = _spPageContextInfo.webId
, webTitle = _spPageContextInfo.webTitle
, listId = _spPageContextInfo.listId
, listTitle = _spPageContextInfo.listTitle
, userEmail = _spPageContextInfo.userEmail
, listTemplateTypeId = _spPageContextInfo.listBaseTemplate
, webUrl = _spPageContextInfo.webAbsoluteUrl
, webLogoUrl = _spPageContextInfo.webLogoUrl
, webTemplate = _spPageContextInfo.webTemplate
, isSiteAdmin = (_spPageContextInfo.isSiteAdmin ? 1 : 0)
, scope = "OPENLIST";
var oneDriveURL = "odopen://sync?";
oneDriveURL += "siteId="+encodeURIComponent(siteId);
oneDriveURL += "&webId="+encodeURIComponent(webId);
oneDriveURL += "&webTitle="+encodeURIComponent(webTitle);
oneDriveURL += "&listId="+encodeURIComponent(listId);
oneDriveURL += "&listTitle="+encodeURIComponent(listTitle);
oneDriveURL += "&userEmail="+encodeURIComponent(userEmail);
oneDriveURL += "&listTemplateTypeId="+encodeURIComponent(listTemplateTypeId);
oneDriveURL += "&webUrl="+encodeURIComponent(webUrl);
oneDriveURL += "&webLogoUrl="+encodeURIComponent(webLogoUrl);
oneDriveURL += "&webTemplate="+encodeURIComponent(webTemplate);
oneDriveURL += "&isSiteAdmin="+encodeURIComponent(isSiteAdmin);
oneDriveURL += "&scope="+encodeURIComponent(scope);
window.location.href = oneDriveURL;
}());
To use the above code, create a new bookmark in your browser of choice. Copy and paste the following line into the bookmark destination:
javascript: (function() { var siteId = _spPageContextInfo.siteId , webId = _spPageContextInfo.webId , webTitle = _spPageContextInfo.webTitle , listId = _spPageContextInfo.listId , listTitle = _spPageContextInfo.listTitle , userEmail = _spPageContextInfo.userEmail , listTemplateTypeId = _spPageContextInfo.listBaseTemplate , webUrl = _spPageContextInfo.webAbsoluteUrl , webLogoUrl = _spPageContextInfo.webLogoUrl , webTemplate = _spPageContextInfo.webTemplate , isSiteAdmin = (_spPageContextInfo.isSiteAdmin ? 1 : 0) , scope = "OPENLIST"; var oneDriveURL = "odopen://sync?"; oneDriveURL += "siteId="+encodeURIComponent(siteId); oneDriveURL += "&webId="+encodeURIComponent(webId); oneDriveURL += "&webTitle="+encodeURIComponent(webTitle); oneDriveURL += "&listId="+encodeURIComponent(listId); oneDriveURL += "&listTitle="+encodeURIComponent(listTitle); oneDriveURL += "&userEmail="+encodeURIComponent(userEmail); oneDriveURL += "&listTemplateTypeId="+encodeURIComponent(listTemplateTypeId); oneDriveURL += "&webUrl="+encodeURIComponent(webUrl); oneDriveURL += "&webLogoUrl="+encodeURIComponent(webLogoUrl); oneDriveURL += "&webTemplate="+encodeURIComponent(webTemplate); oneDriveURL += "&isSiteAdmin="+encodeURIComponent(isSiteAdmin); oneDriveURL += "&scope="+encodeURIComponent(scope); window.location.href = oneDriveURL; }());
Note: this bookmarklet does not work unless you're in the "Documents" page or a specific document folder of your SharePoint site. It will not work from the root page of a SharePoint site, even if "Shared Documents" are shown on the landing page.

How to get a list of installed OLE DB providers?

Microsoft Excel allows import of data from "Other Sources". One of the options is to use an OLE DB provider.
How to get a list of available OLE DB providers?
If you have powershell available, just paste this into a powershell command prompt:
foreach ($provider in [System.Data.OleDb.OleDbEnumerator]::GetRootEnumerator())
{
$v = New-Object PSObject
for ($i = 0; $i -lt $provider.FieldCount; $i++)
{
Add-Member -in $v NoteProperty $provider.GetName($i) $provider.GetValue($i)
}
$v
}
Credits and more advanced usage:
http://dbadailystuff.com/list-all-ole-db-providers-in-powershell
I am answering my own question because this was harder to find that I expected. Google-fu could only answer part of my question; I needed to synthesize information from various blog entries and official documentation.
Below is VBScript you can copy/paste into a text file and run on Windows. You do not need local admin rights to run this version.
Depending on the size of your registry and speed on your CPU, it may take up to one minute to run. The result is a message box with text that can be copied to the clipboard with Ctrl+C.
Primary reference: https://sysmod.wordpress.com/2014/07/11/vbscript-to-list-installed-oledb-providers/
'List of installed OLEDB providers on local computer
Option Explicit
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_CURRENT_CONFIG = &H80000005
Dim OutText, strComputer, objRegistry
Dim num
Dim ProgIdDict
strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
OutText = "Note: Strike Ctrl+C to copy full text to clipboard"
Num = 1
Set ProgIdDict = CreateObject("Scripting.Dictionary")
' I discovered these registrations can appear in three different places.
' Use ProgIdDict to prevent dupes in the output
Append objRegistry, HKEY_CLASSES_ROOT, "HKEY_CLASSES_ROOT", "CLSID", ProgIdDict, Num, OutText
Append objRegistry, HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", "SOFTWARE\Classes\CLSID", ProgIdDict, Num, OutText
Append objRegistry, HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", "SOFTWARE\Classes\Wow6432Node\CLSID", ProgIdDict, Num, OutText
Sub Append(ByVal objRegistry, ByVal HKEYConstant, ByVal HKEYConstantStr, ByVal KeyPrefixStr, ByVal ProgIdDict, ByRef Num, ByRef OutText)
Dim Key, arrKeys
Dim strKeyPath, strValue, uValue
objRegistry.enumKey HKEYConstant, KeyPrefixStr, arrKeys
for each key in arrKeys
strKeyPath = KeyPrefixStr & "\" & key
' if key exists...
' I noticed something weird where non-MSOLAP entries use the first style,
' and MSOLAP entries use the second style.
If 0 = objRegistry.GetDWordValue(HKEYConstant, strKeyPath, "OLEDB_SERVICES", uValue) _
Or 0 = objRegistry.GetDWordValue(HKEYConstant, strKeyPath & "\OLEDB_SERVICES", "", uValue) _
Then
objRegistry.GetStringValue HKEYConstant,strKeyPath & "\ProgID","",strValue
If Not ProgIdDict.Exists(strValue) _
Then
ProgIdDict.Add strValue, strValue
OutText=OutText & vbcrlf & vbcrlf
'get the (Default) value which is the name of the provider
objRegistry.GetStringValue HKEYConstant,strKeyPath,"",strValue
OutText=OutText & num & ") " & strValue & vbcrlf & "Key: \\" & HKEYConstantStr & "\" & KeyPrefixStr & "\" & key
' and the expanded description
objRegistry.GetStringValue HKEYConstant,strKeyPath & "\OLE DB Provider","",strValue
OutText=OutText & vbcrlf & "OLE DB Provider: " & strValue
objRegistry.GetStringValue HKEYConstant,strKeyPath & "\ProgID","",strValue
OutText=OutText & vbcrlf & "ProgID: " & strValue
objRegistry.GetStringValue HKEYConstant,strKeyPath & "\VersionIndependentProgID","",strValue
OutText=OutText & vbcrlf & "VersionIndependentProgID: " & strValue
num = 1 + num
End If
end if
next
End Sub
Wscript.Echo OutText
Another solution using PowerShell, this time leveraging .NET code (credit to jrich523.wordpress.com).
Plug this into a PowerShell console:
(New-Object system.data.oledb.oledbenumerator).GetElements()
Produces output like this:
SOURCES_NAME : SQLOLEDB Enumerator
SOURCES_PARSENAME : {DFA22B8E-E68D-11d0-97E4-00C04FC2AD98}
SOURCES_DESCRIPTION : Microsoft OLE DB Enumerator for SQL Server
SOURCES_TYPE : 2
SOURCES_ISPARENT : False
SOURCES_CLSID : {DFA22B8E-E68D-11d0-97E4-00C04FC2AD98}
In Windows Explorer:
Create a text file anywhere. e.g. temp.txt.
Change the extension to "udl". E.g. temp.udl.
Double click temp.udl.
Go to the [Provider] Tab. Observe the list of "OLE
OLEDB provides a class that will enumerate all OLE DB providers for you.
Microsoft OLE DB Root Enumerator🕗
ProgID: "MSDAENUM"
clsid: {c8b522d0-5cf3-11ce-ade5-00aa0044773d}
CLSID_OLEDB_ENUMERATOR (from msdaguid.h in the sdk)
The steps
Create the enumerator
ISourcesRowset enum = (ISourcesRowset)CreateComObject(CLSID_OLEDB_ENUMERATOR);
Get the results as an OLEDB IRowset:
IRowset rowset = enum.GetSourcesRowset(null, IRowset, 0, null);
The IRowset interface, like the rest of OLEDB is...merciless. It's a nightmare of API, dreamed up in a time when Java was all the rage. Fortunately Microsoft created a friendly wrapper around OLEDB: called ActiveX Data Object (ADO). It even provides a handy function to wrap an OLEDB IRowset into an ADO Recordset (adapter pattern):
Recordset rs = (Recordset)CreateComObject(CLASS_Recordset);
(rs as ADORecordsetConstruction).Rowset = rowset;
Now you can iterate the results:
SOURCES_NAME SOURCES_PARSENAME SOURCES_DESCRIPTION SOURCES_TYPE SOURCES_ISPARENT SOURCES_CLSID
-------------------------- -------------------------------------- ---------------------------------------------------- ------------ ---------------- --------------------------------------
SQLOLEDB {0C7FF16C-38E3-11d0-97AB-00C04FC2AD98} Microsoft OLE DB Provider for SQL Server 1 False {0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}
MSOLAP {10154F28-4979-4166-B114-3E7A7926C747} Microsoft OLE DB Provider for Analysis Services 10.0 1 False {10154F28-4979-4166-B114-3E7A7926C747}
MSOLAP {10154F28-4979-4166-B114-3E7A7926C747} Microsoft OLE DB Provider for Analysis Services 10.0 3 False {10154F28-4979-4166-B114-3E7A7926C747}
MSDataShape {3449A1C8-C56C-11D0-AD72-00C04FC29863} MSDataShape 1 False {3449A1C8-C56C-11D0-AD72-00C04FC29863}
SQLNCLI11 {397C2819-8272-4532-AD3A-FB5E43BEAA39} SQL Server Native Client 11.0 1 False {397C2819-8272-4532-AD3A-FB5E43BEAA39}
ADsDSOObject {549365d0-ec26-11cf-8310-00aa00b505db} OLE DB Provider for Microsoft Directory Services 1 False {549365d0-ec26-11cf-8310-00aa00b505db}
MSOLEDBSQL {5A23DE84-1D7B-4A16-8DED-B29C09CB648D} Microsoft OLE DB Driver for SQL Server 1 False {5A23DE84-1D7B-4A16-8DED-B29C09CB648D}
MSOLEDBSQL Enumerator {720818D5-1465-4812-839F-9F15C38A52CB} Microsoft OLE DB Driver for SQL Server Enumerator 2 False {720818D5-1465-4812-839F-9F15C38A52CB}
SQLNCLI11 Enumerator {8F612DD2-7E28-424f-A2FD-C2EECC314AA2} SQL Server Native Client 11.0 Enumerator 2 False {8F612DD2-7E28-424f-A2FD-C2EECC314AA2}
Windows Search Data Source {9E175B8B-F52A-11D8-B9A5-505054503030} Microsoft OLE DB Provider for Search 1 False {9E175B8B-F52A-11D8-B9A5-505054503030}
MSDASQL {c8b522cb-5cf3-11ce-ade5-00aa0044773d} Microsoft OLE DB Provider for ODBC Drivers 1 False {c8b522cb-5cf3-11ce-ade5-00aa0044773d}
MSDASQL Enumerator {c8b522cd-5cf3-11ce-ade5-00aa0044773d} Microsoft OLE DB Enumerator for ODBC Drivers 2 False {c8b522cd-5cf3-11ce-ade5-00aa0044773d}
MSOLAP {DBC724B0-DD86-4772-BB5A-FCC6CAB2FC1A} Microsoft OLE DB Provider for Analysis Services 14.0 1 False {DBC724B0-DD86-4772-BB5A-FCC6CAB2FC1A}
MSOLAP {DBC724B0-DD86-4772-BB5A-FCC6CAB2FC1A} Microsoft OLE DB Provider for Analysis Services 14.0 3 False {DBC724B0-DD86-4772-BB5A-FCC6CAB2FC1A}
Microsoft.Jet.OLEDB.4.0 {dee35070-506b-11cf-b1aa-00aa00b8de95} Microsoft Jet 4.0 OLE DB Provider 1 False {dee35070-506b-11cf-b1aa-00aa00b8de95}
SQLOLEDB Enumerator {DFA22B8E-E68D-11d0-97E4-00C04FC2AD98} Microsoft OLE DB Enumerator for SQL Server 2 False {DFA22B8E-E68D-11d0-97E4-00C04FC2AD98}
MSDAOSP {dfc8bdc0-e378-11d0-9b30-0080c7e9fe95} Microsoft OLE DB Simple Provider 1 False {dfc8bdc0-e378-11d0-9b30-0080c7e9fe95}
MSDAORA {e8cc4cbe-fdff-11d0-b865-00a0c9081c1d} Microsoft OLE DB Provider for Oracle 1 False {e8cc4cbe-fdff-11d0-b865-00a0c9081c1d}
Microsoft documents the columns in ISourcesRowset::GetSourcesRowset archive
SOURCES_NAME (0): The invariant name of the data store or enumerator.
SOURCES_PARSENAME (1): String to pass to IParseDisplayName to obtain a moniker for the data source object or enumerator.
SOURCES_DESCRIPTION (2): Description of the OLE DB data source object or enumerator.
SOURCES_TYPE (3): Specifies whether the row describes a data source object or an enumerator:
DBSOURCETYPE_DATASOURCE_TDP (1): Indicating a tabular data provider
DBSOURCETYPE_ENUMERATOR (2): Indicating an enumerator
DBSOURCETYPE_DATASOURCE_MDP (3): Indicating a multidimensional (OLAP) provider
DBSOURCETYPE_BINDER (4): Indicating a provider binder that supports direct URL binder
If a single piece of code is capable of being used both as a data source object and as an enumerator, it is listed in the rowset twice, once in each role.
SOURCES_ISPARENT (4): If the row describes an enumerator, SOURCES_ISPARENT is VARIANT_TRUE if the enumerator is the parent enumerator; that is, the enumerator whose enumeration contains the enumerator on which ISourcesRowset::GetSourcesRowset was just called. This allows the consumer to go backward through the enumeration. Whether an enumerator is able to enumerate its parent is provider-specific. Otherwise, SOURCES_ISPARENT is VARIANT_FALSE.
If the row describes a data source object, SOURCES_ISPARENT is ignored by the consumer.
I had an issue where Steinar Herland's powershell script wasn't finding my oledb provider. I wrote a little C# program that did though.
using System.Data.OleDb;
var oleEnum = new OleDbEnumerator();
var elems = oleEnum.GetElements();
if (elems != null && elems.Rows != null)
foreach (System.Data.DataRow row in elems.Rows)
if (!row.IsNull("SOURCES_NAME") && row["SOURCES_NAME"] is string)
Console.WriteLine(row["SOURCES_NAME"]);
If you have MS Excel installed, why go thru all the hassle of all these scripts/powershell? You can use Excel Import Data from Other Source and it will display all installed OLEDB Data Sources.
I edited the code by #Steinar Herland
If you want only to display the ACCESS OLEDB Providers, just paste this into a powershell command prompt:
foreach ($provider in [System.Data.OleDb.OleDbEnumerator]::GetRootEnumerator())
{
if ($provider.GetValue(0) -like "Microsoft.ACE*")
{
$v = New-Object PSObject
Add-Member -in $v NoteProperty "Provider Name" $provider.GetValue(0)
Add-Member -in $v NoteProperty "Description" $provider.GetValue(2)
$v
}
}

How to manage MS Dynamics NAV C/AL Codes in TFS with versioning

I need to keep all MS Dynamics NAV development codes in TFS, currently I export NAV objects in FOB/TXT format and add these to TFS. But I am not able to leverage the advantages of TFS, like versioning, check-in, check-out process etc., so its unmanageable between development team and QA team.
As MS Dynamics NAV keep their Codes in SQL database, I have only option to export the objects and manually add in TFS.
Experts, please advice me how could I manage these all in TFS, like we manage Visual Studio projects.
Thanks
Kishore
There isn't any native options for source control in Dynamics NAV at this point (how amazing Git integration would be!), unless you manually export text files...
There are however some paid developments such as Object Manager that do integrate with TFS and VSS. They have a concept of projects which I believe map to branches and so on. IDYN have a trial, so it might be worth downloading it and trying it out first, as it's still a bit shaky for 2013.
I'm a bit of a noob to NAV development, and was unable to find a good ready-made way to get all objects that I have permission to export out into text files that could be meaningfully source-controlled, so I wrote this powershell script that attempts to export all of them and just moves on when it gets the permission error.
#### change these params to point this script at a different server or different directory ####
$serverName = "server_where_nav_db_lives"
$dbname = "name_of_your_nav_db"
$destFolder = "c:\TestNavExport"
$startTime = [System.DateTime]::Now
function doExport {
param ([string]$type, [string]$id, [string]$name, [string]$svr, [string]$db, [string]$dest)
$cleanName = $name.replace("/", "")
$filepath = "`"{0}\{1}s\{2} - {3}.txt`"" -f $dest, $type, $id, $cleanName
write-host "filepath is $filepath"
### change this value to use a different version of the dev environment
$finpath = "c:\program Files (x86)\Microsoft Dynamics NAV\71\RoleTailored Client - CU25\finsql.exe"
$args = "command=exportobjects, file=$filepath, servername=$svr, database=$db, ntauthentication=yes, logfile=`"$dest\exportlog-$type-$cleanName.txt`", filter=`"Type=$type;ID=$id`" "
Start-Process $finpath -ArgumentList $args -Wait
}
function CheckExists {
param ([string]$pth)
if (-Not [System.IO.Directory]::Exists($pth)) { md -Path $pth }
}
$qry = #"
SELECT
o.ID,
o.[Name],
o.[Type],
CASE o.[Type] WHEN 0 THEN 'Table'
WHEN 3 THEN 'Report'
WHEN 5 THEN 'CodeUnit'
WHEN 6 THEN 'XMLPort'
WHEN 7 THEN 'MenuSuite'
WHEN 8 THEN 'Page'
WHEN 9 THEN 'Query'
ELSE 'Other'
END ObjType
FROM [Object] o
WHERE o.[Type] IN (0, 3, 5, 6, 7, 8, 9)
AND o.[ID] < 150
ORDER BY o.[ID]
"#
# make sure all the necessary directories exist
CheckExists $destFolder
CheckExists "$destFolder\Tables"
CheckExists "$destFolder\CodeUnits"
CheckExists "$destFolder\Pages"
CheckExists "$destFolder\Reports"
CheckExists "$destFolder\XMLPorts"
CheckExists "$destFolder\MenuSuites"
CheckExists "$destFolder\Querys"
# query the database for all of the objects
$connection = new-object system.Data.SqlClient.SqlConnection("Server=$serverName;Database=$dbname;Trusted_Connection=True")
$connection.Open();
$cmd = $connection.CreateCommand();
$cmd.CommandText = $qry;
$cmd.Connection = $connection;
$reader = [System.Data.SqlClient.SqlDataReader]$cmd.ExecuteReader()
while ($reader.Read()) {
$cid = $reader["ID"];
$cname = $reader["Name"]
$ctype = $reader["Type"]
$cTypeName = $reader["ObjType"]
write-host "exporting $cname $cid $ctypename"
doExport $cTypeName $cid $cname $serverName $dbname $destFolder
}
$connection.Close()
$endTime = [System.DateTime]::Now
("start time {0}, end time {1}, span {2}" -f $startTime, $endTime, ($endTime - $startTime)) | out-file "$destFolder\clock.txt"
I also found this other question, which shows how to get that text out of the object metadata table. This article has sample code that looks like it could translate the blobs in the metadata table into the text. Having written the script and verified that it works, I've stuck with the script so far. As a noob, I will not be too surprised if I find a much more efficient solution soon.
For some time we've used Visual Studio plug-in. It worked for VS2008 and NAV up to version 5.
It allowed to import and export code from/to Nav by pressing buttons in VS as well as check-in/check-out.
I hope this link still works.
But I must say it was not really a convenient solution and it lacked some important features for source code management.
You can also look at third-party solutions like ToIncreaseSolutions and ifacto

SharePoint 2010 - Add list item with workflow approval status and PowerShell

I want to add a item to a SharePoint 2010 list by using PowerShell.
This list is related with the standard SharePoint Approval Workflow.
I want to add Items and set the workflow status to "Published" with PowerShell.
My Code, but how it is possible to set the Workflow status to "Published"?
$web = Get-SPWeb $Url
$list = $web.Lists["MyList"]
$newitem = $Schulliste.items.Add()
$newitem["Column1"] = "Test1" # Works fine!
#Set Column Writable
$column = $list.Fields["WorkflowName"]
$column.Hidden = $false
$column.ReadOnlyField = $false
$column.Update()
#Update Workflow Item
$newitem["WorkflowName"] = "Published" #Not working
$newitem.update()
#Set Column Readonly
$column = $list.Fields["WorkflowName"]
$column.Hidden = $true
$column.ReadOnlyField = $true
$column.Update()
I think, setting the Status field is not the right way. You should approve the item programatically.
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spfile.approve.aspx
$newitem.File.Approve("approved by script")
My workaround now is to activate and deactivate the content approval
$web = Get-SPWeb $Url
$list = $Web.Lists["MyList"]
$list.EnableModeration = $false
$list.Update()
$newitem = $liste.items.Add()
$newitem["Column1"] = "Test1"
$newitem.update()
$list.EnableModeration = $true
$list.Update()

Resources