Create a function library in Power BI using M-Extensions

Having the ability to use own M-function the same way than native functions in Power BI and Excel has been one of my biggest wishes for quite some time. So I was more than amazed to see Frank Tonsen’s comment showing a way to do exactly this in PowerBI, that has been available for almost half a year now: M-Extensions as part of the custom connectors.

Unlike custom connectors who show up in the import-dialogue and provide a custom tailored option for importing data or creating queries, M-Extensions don’t show up explicitly anywhere in Power BI: They just do their M(agic) job to make the functions that you’ve defined in them accessible, as if they were inbuilt native functions: Type their name into the formula bar like this (1):

And enjoy the function description (2: if you’ve specified it in the definition, which is optional):

Simplest example

  1. Your functions: Number.Double and Number.Triple
  2. Combined with the keyword “shared” and separated by “;”
  3. Prefix by “section MyLibrary” gives this text:
section MyLibrary;
shared Number.Double = (Number as number) =>
2 * Number;
shared Number.Triple = (Number as number) =>
3 * Number;


How to make M-Extensions work

The following steps have been updated at 2018-July-04 (no need to restart PBID after you’ve added or updated mez-files):

  1. copy the text to a text editor
  2. save it as “MyLibrary.mez”
  3. copy this file to the folder: C:\Users\<YourUserName>\Documents\Microsoft Power BI Desktop\Custom Connectors (or like described in here)
  4. if you haven’t already:  enable custom connector option in the preview features
  5. use the functions
  6. dance the happy dance

What I also learned from Frank was that we even don’t need Visual Studio for it here, so this is really lightweight.


  • This currently just works for Power BI Desktop and via gateways in the Power BI Service. Currently they don’t work in Excel.
  • Functions using #shared will not work (if you have a function with #shared in your .mez-file, the whole file will be ignored)
  • The same goes for functions using R.Execute: The will make the whole .mez-file invalid.


It’s nice that one can have multiple library.mez files in the folder, so you can only ship what’s necessary or work with external libraries without having to merge them with yours. To make this work, they have to have unique section names (like “section MyStatsLibrary” or “section IgorsCoolFunctions”). Also errors will be thrown if a function with the same name appears in more than one library. I will leave this aspect for another blogpost, as there are a couple of implications and possibilities that come with this.

Enjoy & stay queryious 🙂

Comments (14) Write a comment

  1. imke, but if you share the pbix file, does the function works, or the new users need to install the library too ?


    • Hi mim,
      good point: Currently, the library files (.mez) have to sit on each machine where the files shall be opened (just like the other custom connectors as well).
      But as this doesn’t require an installation, you’re independent from admins 🙂
      Cheers, Imke


  2. There should be an online portal for custom functions, just like for custom visuals. You would be able to search and browse through those functions. Functions should have descriptions and tags. PBI would be able to automatically download each function that is explicitly referenced in your file “Variable = OnLineDepository:SomeFunction(x,y)”.
    Someone already posted this idea, you can vote for this idea here:


    • Yes, that sounds great. However, there come some implications with it when
      1) these custom functions reference other custom functions and
      2) people want to share different functions with the same name
      I will cover these aspects in the follow-up-article here soon.


    • Hi sam,
      it works for me, but I’ve built it with Visual Studio. Will check tomorrow how it works with the text-editor only.
      Please be aware that this “data-connnector” again has no import-dialogue like you’d normally expect. It is just available from the function calls like shown in Chris’ sample pbix. (The queries in the group referencing comments on his blogpost didn’t work either, but as they reference local files, this isn’t to expect).
      Cheers, Imke


      • I can confirm that the simple compression of the text-file does NOT work for custom connectors.
        So you have to go via Visual Studio to create the .mez file for it.


  3. Hi Imke,

    Thanks for the article. I’ve been meaning to put my custom functions in M extension libraries (organized by category), but when I think of having to add documentation for over 100 general purpose functions…well, sigh. However, it’s got to be done, since like you, I’ve been waiting for this kind of functionality for a long time. Your article might be my wake-up call. 🙂


  4. Pingback: DAX CALCULATE Debugger – The BIccountant

  5. Pingback: Present Value (PV) function for Power Query – The BIccountant

Leave a Reply