Showing posts with label automation. Show all posts
Showing posts with label automation. Show all posts

Automate moving measures between Power BI files .pbix, renaming and finding and replacing strings in DAX formula\expression

Yesterday I had to accomplish a task that got me thinking: this is going to take a hell of a lot of time to finish.

The user story is this: I have a Power BI .pbix file that is used somewhat as a staging\debugging file to try and test measures. Once the job is done I usually move things over to the final\main Power BI file which will be handed in to the client. Note that this final Power BI file already has report pages implemented. That's way I try things in a different file since the work can be done in a cleaner\faster model.
The problem this time was that I had to create\move lots of measures and so I'd have to do this measure by measure from the debugging file to the main file. It would take me about 1 hour to finish. Unfortunately Power BI has no built in copy\paste of measures between files as of today in its version 2.72.5556.801 64-bit (August 2019). At least we can copy and paste the visuals from one file to the other.

OK. Problem defined. Let's Google for a solution. The solution found was this awesome post titled Bulk measure handling (copy between reports/format changes). In this post the guy mentions the tool Tabular Editor. Well that was what I was looking for, really.

Just downloaded it directly from its GitHub repo here.

Followed the steps on that post and voilá: I could get more than 30 measures copied from one .pbix file to another. Great! This took me about 10 minutes to get done. 1\6 of the time previously estimated for that cumbersome\manual work. Check the following printscreen:

1st printscreen - measures moved from one Power BI file (on the left) to the other Power BI file (on the right)

2nd printscreen - batch renaming selected formulas in blue
There was another task that needed to be accomplished and it was a little bit different: needed to duplicate those copied measures. Tabular Editor makes it easy too. Just select all of them, right click and pick Duplicate # measures. Boom! You have all measures duplicated as seen in the printscreen on the right. Note that it adds a "copy" word to the measure name. So once the measures are duplicated we need to rename them and that's easy too. Select all duplicated measures, right click and pick Batch rename.

Just replaced the uppercase U in each formula name to a uppercase C as seen in the second printscreen above. Repeated the process and replaced " copy" with a blank string. That's it. Measures duplicated and renamed accordingly. Nonetheless there's still a missing step before theses measures are ready to go: change a table column name in the DAX formula\expression in each of these measures that got duplicated and renamed. How to get this done using Tabular Editor? Well, reading through its docs we can find this Advanced Scripting section. If you look at the first printscreen above you'll note that I wrote some C# code there that does exactly what is needed. See the code below:

Selected.Measures.ForEach(m => {
    var e = m.Expression;
   
    if(e.Contains("[Unit]"))
    {       
        e = e.Replace("[Unit]", "[Company]");
       
        // For debugging purposes
        //e.Output();
       
       
m.Expression = e;     
    }
});


What this piece of code is doing is that for each of the selected measures in blue on the left (see printscreens above), the measure DAX formula\expression is stored in a variable called e. I then check if this formula contains the word [Unit] that is the table column name that needs to be replaced. If the expression\formula contains this word it gets replaced with the word [Company] that refers to the other column name that is to be used in these duplicated formulas. After that the modified DAX formula is assigned back to the measure.

When finished with Tabular Editor, click Save. Return to Power BI and hit the Refresh button to reload the model.

This post is just a sample that showcases the power of Tabular Editor. You can manage and play with measures in any way imaginable.

I hope it helps someone that wants to accomplish trivial things in a more actionable way instead of having to copy\paste, rename and replace manually because that sucks.

Note: when trying to save back the modifications done in Tabular Editor an error was being displayed. Something along this line:

Failed to save modifications to the server. Error returned: 'Unexpected column name: Received column 'ObjectID.Expression' in rowset 'ObjectTranslations'. Expected column 'ObjectID.Set'.'.

I did the following to get rid of the nasty error message: opened Tabular Editor File menu and selected Preferences... checked "Allow unsupported Power BI features (experimental)". When we do this a new Translations folder appear in the Model tree. I just deleted the en-US that was under this folder (see printscreen below). Then tried saving again and it worked.

3rd printscreen - enabling Allow unsupported Power BI features (experimental) in Tabular Editor

Software to automate website screenshot capture

I needed a software that allowed me to capture screenshots of a web application I developed. The software should do it automatically (batch capture). This way it’d save me a lot of time.

How do I used to do that?
I visited each web page I wanted to take a screenshot. It took me about 1 hour to finish the work.

I posted a question at Super User as always: Software to automate website screenshot capture and got an answer suggesting that I use a combination of a URL fetcher + Selenium capability to take screenshots.

Well, I tried Selenium (.NET bindings selenium-dotnet-2.0rc3.zip ) to test its screenshot capture feature but it doesn’t seem to fit the job because it doesn’t allow you to configure screenshot properties as size (height x width). Moreover it doesn’t work well with Ajax (requires you to write a lot of code to check for the existence of Ajax calls, etc). This kills a screenshot that needs everything in place (I mean every DOM object should be part of the screenshot). I tried the 3 drivers available: Internet Explorer, Firefox and Chrome. Screenshots taken with Internet Explorer driver were close to what I expected.

This is a sample code I used based on the code taken from here:

using System;
using System.Drawing.Imaging;
using System.Text;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;

namespace SeleniumTest
{
    [TestFixture]
    public class SeleniumExample
    {
        private FirefoxDriver firefoxDriver;
    
        #region Setup

        [SetUp]
        public void Setup()
        {
            firefoxDriver = new FirefoxDriver();
        }

        #endregion

        #region Tests

        [Test]
        public void DisplayReport()
        {
            // Navigate
            firefoxDriver.Navigate().GoToUrl("http://localhost/FitnessCenter/Report/TotalPaymentsByPeriod");

            IWebElement startDate = firefoxDriver.FindElement(By.Name("StartDate"));
            
            startDate.Clear();
            startDate.SendKeys("January 2011");

            IWebElement generate = firefoxDriver.FindElement(By.Id("Generate"));
            generate.Click();

            var wait = new WebDriverWait(firefoxDriver, TimeSpan.FromSeconds(5));
            wait.Until(driver => driver.FindElement(By.Id("Map")));

            SaveScreenShot(firefoxDriver.Title);
        }

        /// <summary>
        /// Saves a screenshot of the current error page
        /// </summary>
        public void SaveScreenShot(string fileName)
        {
            // Get the screenshot
            Screenshot screenshot = firefoxDriver.GetScreenshot();

            // Build up our filename
            StringBuilder filename = new StringBuilder(fileName);
            filename.Append("-");
            filename.Append(DateTime.Now.ToString("yyyy-MM-dd HH_mm_ss"));
            filename.Append(".png");

            // Save the image
            screenshot.SaveAsFile(filename.ToString(), ImageFormat.Png);
        }

        #endregion

        #region TearDown

        [TearDown]
        public void FixtureTearDown()
        {
            if (firefoxDriver != null) firefoxDriver.Close();
        }

        #endregion
    }
}

Indeed, Selenium is powerful for what it does, that is, helping you automate browser interactions while you test your code. It even allows you to take a screenshot let’s say when something goes wrong (a test fail for example). That’s great and that’s what it does best. It’s a choice for every operating system since it’s an API that can be programmed against.

Paparazzi! beautiful application iconWhat I needed was something more specialized to take screenshots. A software that allows me to configure screenshot properties. The good news is that I managed to find such piece of software and it’s called Paparazzi! - a very suggestive name by the way. One drawback is that it’s only available for Mac OS. As one would expect, it uses Safari browser engine behind the curtains to capture the screenshots. Paparazzi! has minor bugs but it gets the job done. It doesn’t have documentation. I had a hard time trying to make it work. It has batch capture capability but no docs explaining how to do it. So I hope this post will shed some light…

The following lines describe what I did to achieve my objective with Paparazzi!:

1 - Created a list of URLs I’d like to take screenshots of. Like this (one URL per line):

http://192.168.1.106/FitnessCenter/Account/ChangeCulture?lang=en&returnUrl=%2FFitnessCenter%2F
http://192.168.1.106/FitnessCenter/Student
http://192.168.1.106/FitnessCenter/Student/Create
http://192.168.1.106/FitnessCenter/Student/Edit/79
http://192.168.1.106/FitnessCenter/Student/Details/79
http://192.168.1.106/FitnessCenter/Student/Delete/79
http://192.168.1.106/FitnessCenter/Anamnesis
http://192.168.1.106/FitnessCenter/Anamnesis/Create
http://192.168.1.106/FitnessCenter/Anamnesis/Edit/79
http://192.168.1.106/FitnessCenter/Anamnesis/Details/79

.
.
.

2 - Open Paparazzi! and click the Window menu => Batch capture (really difficult to find this option Disappointed smile ):

Paparazzi! difficult to find Batch Capture menu optionPicture 1 - Paparazzi! difficult to find Batch Capture menu option

3 - Drag and drop a text file .txt (the file that contains the URLs) to the Batch Capture window:

Paparazzi! Batch Capture window surfacePicture 2 - Paparazzi! Batch Capture window surface

Here is where I think I found a limitation and it’s by design. This should definitely not happen IMHO. If you try to add a file clicking on ( + button), Paparazzi won’t let you select a text file. The only way I got it working was selecting the .txt file and then drag and dropping the file to the Batch Capture window.

4 - Configure screenshot properties by clicking the list button (see mouse cursor above it):

Paparazzi! screenshot process basic configurationsPicture 3 - Paparazzi! screenshot process basic configurations

You can define the screenshot size. There are pre-defined values for standard screen resolutions. It allows you to define new presets.

You can also delay the capture to wait the page finish loading, etc.

There are a set of configurations available related to the batch capture functionality. To access these configurations, go to Paparazzi! menu and select Preferences:

Paparazzi! Preferences… menu optionPicture 4 - Paparazzi! Preferences… menu option

The first configuration worth mentioning the Default Filename Format available in the General section:

Paparazzi! General preferences sectionPicture 5 - Paparazzi! General preferences section

Above I’m defining this format:

%t = page title
%Y = year
%m = month
%d = day
%H = hour
%M = minute
%S = second

The example in the picture is pretty clear… Smile

Another set of configurations is available in the Batch capture section:

Paparazzi! Batch Capture preferences sectionPicture 6 - Paparazzi! Batch Capture preferences section

Here you can choose where to save the screenshots as well as the type of the images.

After configuring the batch capture session, it’s the gran finale time...

5 - Click the Play button, go take a coffee and relax while the computer does the job for you Fingers crossed.

Paparazzi! Batch Capture in actionPicture 7 - Paparazzi! Batch Capture in action

Hope you have found this post interesting and that it’s useful to help in documenting a little bit of this small but really powerful application.

Pointing up Now I get all the screenshots in less than 1 minute!

References
Paparazzi!
http://derailer.org/paparazzi/

Add Songs to iTunes Playlist with Automator

Last time I showed you how to Automate tasks in Mac OS with Automator. I used Automator to create a simple workflow that helps moving MP3 files to iTunes folder. Check that here.

Now I have another task to Automator.

This is the description of what I want to accomplish or the problem description if you prefer:

I often download some free legal MP3 files from the internet for evaluation, more specifically from Indie Rock Cafe (great great site by the way :D - check it out if you like Indie Rock music). I use IndieRockCafe mainly to discover bands that I’ve never heard about. It’s being a great experience so far. I’ve come to know some really good bands that, else I would never hear a song of theirs.

To download those MP3s I use DownThemAll that is a really nice piece of software that works beautifully with Firefox. I wrote about DownThemAll in Automate the download of a list of URLs/links. Although I didn’t write how to download only MP3 files with DownThemAll, this post gives you an idea about the purpose of DownThemAll. I’ll write about how to download only specific kind of files (MP3 in this case) using DownThemAll, but that’s another post. Probably I’ll detail this download process I’m mentioning here.

As I was telling you, I often do the same task, that is, I go to IndieRockCafe, click on DownThemAll icon in my Firefox toolbar and tada, the download of IndieRockCafe’s recently added MP3s just start. DownThemAll will download only page links that point to MP3 files saving these MP3 in a single folder called IndieRockCafe.

After the download I used to select all the files within that folder and drag and drop them inside an iTunes playlist called IndieRockCafe. iTunes is wise enough to tell me that some files are already part of the playlist and gives me the option to skip them adding only new files into that playlist. Doing so I always have a fresh playlist with the latest files of IndieRockCafe. It works, but it has a lot of manual steps.

Yesterday I thought: the above steps are a perfect fit to be automated with Automator.

Let’s create a workflow:

1 - Go to the Applications folder and select Automator.

2 - You’ll be presented with the following screen to choose a template for your workflow. Select Folder Action as the template.

Types of templates available to create an Automator workflow (Folder Action)Figure 1 - Types of templates available to create an Automator workflow (Folder Action)

3 - In Folder Action receives folders and files added to, select the folder you want. In my case it is the IndieRockCafe folder.

4 - Now select Music in Library list and then select Import Files into iTunes under the Actions list. Drag this action to the workflow area in the right.

5 - Select Existing playlist and the playlist you want the files to go to. As I wrote above I already have a Playlist called IndieRockCafe inside iTunes. So I selected it.

6 - Go to the File menu and select Save. Give the workflow an appropriate name, e.g. IndieRockCafe.

The following screenshot shows the Folder Action workflow configured:

IndieRockCafe.workflow configured according to the six steps described above
Figure 2 - IndieRockCafe.workflow configured according to the six steps described above

7 - Now that the workflow is created, there’s a last step required to orchestrate things: go to the IndieRockCafe folder and right-click it. Select Services > Folder Actions Setup… Make sure you attach the IndieRockCafe workflow to this folder as shown in Figure 3:

Attaching IndieRockCafe.workflow in Folder Actions Setup
Figure 3 - Attaching IndieRockCafe.workflow in Folder Actions Setup

Make sure you click the Enable Folder Actions checkbox too:

Enabling Folder Actions and turning IndieRockCafe.workflow ON for the IndieRockCafe folder
Figure 4 - Enabling Folder Actions and turning IndieRockCafe.workflow ON for the IndieRockCafe folder

… and we’re done! As you see this is totally life saver.

Every new MP3 that gets added in my IndieRockCafe folder through DownThemAll or that I manually place in this folder will be automatically added in IndieRockCafe playlist.

Task successfully automated!

I’m a music lover and I hope you can take advantage of it too.

Important
DownThemAll creates file segments ( *.dtapart files ) while downloading. DownThemAll splits the file into several parts and then downloads each segment of the file individually, which gives you better speed from servers, especially those that choose to limit your download speed. This behavior will cause the workflow created above to fail because iTunes won’t recognize those parted files when trying to import them. To solve this problem, do the following:

In Firefox Tools menu choose More dTa Tools and then select Preferences.

In tab Advanced and under Temporary files choose a directory to store those dtapart files. See screenshot below to have an idea:

Using a temporary folder to store DownThemAll file parts or segmentsFigure 5 - Using a temporary folder to store DownThemAll file parts or segments

Doing the above, DownThemAll will store those partial files in a separate folder. When it finishes downloading a file it will join its parts and then will move that file to the IndieRockCafe folder I specified in the workflow. Now iTunes will import the MP3.

Note
Folder action workflows are saved in
/Users/YourUserName/Library/Workflows/Applications/Folder Actions

Download
You can download this workflow at:
https://sites.google.com/site/leniel/blog/IndieRockCafe.workflow.zip

Automate tasks in Mac OS with Automator

This one is about an incredible application that comes with Mac OS X. Its name is Automator.

Jesus Christ, this is a life saver app!

This is the description of Automator:Automator Apple Mac OS application icon

With Automator, you can accomplish time-consuming, repetitive manual tasks quickly, efficiently, and effortlessly. Automator lets you skip the complex programming and scripting that is normally required to create automations. Instead, you assemble individual steps into a complete task by dragging these actions into an Automator workflow. Automator comes with a library of hundreds of actions. And with the Watch Me Do action, you can record an action — such as pressing a button or controlling an application without built-in Automator support — and replay it as an action in a workflow.

I have lots of MP3 files that I need to go through analyzing if I really want to keep them in my media library. During the last year I stored all those MP3 in a folder and such a folder is now 55.56 GB and contains 11840 files to be precise. That’s a lot of MP3! I keep postponing this open/listen to task but today I thought I’d start. That’s where Automator fits the job.

In this post I’ll show you how to create a simple workflow that helps moving the MP3 files to iTunes folder /Users/leniel/Music/iTunes/iTunes Media/Automatically Add to iTunes. The folder Automatically Add to iTunes is a special folder that iTunes keeps watching for new files added to it. When a file is added in this folder, iTunes automatically adds it to the media library using MP3 metadata to organize the library. When added files will reside in /Users/leniel/Music/iTunes/iTunes Media/Music.

Let’s create the workflow:

1 - Go to the Applications folder and select Automator.

2 - You’ll be presented with the following screen to choose a template for your workflow. Select Service as the template.

Types of templates available to create an Automator workflow
Figure 1 - Types of templates available to create an Automator workflow

3 - In Service receives selected, select audio files. “In” select Finder.

4 - Now select Files & Folders in Library list and then select Move Finder Items under the Actions list. Drag this action to the workflow area in the right.

5 - In Move Finder Items select the folder where you want the files to be moved to. You also have the option of showing the action when the workflow runs.

6 - Go to the File menu and select Save. Give it an appropriate name as Add to iTunes and you’re done.

The following screenshot shows the Service workflow configured:

Add to iTunes.workflow configured according to the six steps described above 
Figure 2 - Add to iTunes.workflow configured according to the six steps described above

Now, let’s use this service workflow. To do this, go to Finder and open any folder that contains audio files such as MP3. Right click the MP3 file and voila. Now there’s an extra context menu option called Add to iTunes. What a marvelous thing.

Add to iTunes context menu option in Finder when right clicking MP3 file(s)
Figure 3 - Add to iTunes context menu option in Finder when right clicking MP3 file(s)

What happens when Add to iTunes is clicked? The workflow we created will be executed and the selected file(s) will be moved to the folder specified in the workflow, in this case /Users/leniel/Music/iTunes/iTunes Media/Automatically Add to iTunes.

As you see this is totally life saver.

I can play the MP3 in iTunes and if I decide that I want to keep it in my media library I just have to select Add to iTunes.

The possibilities with Automator are endless given the amount of options in its Library and Actions lists and workflow template types.

I hope you could get an idea of what Automator can do.

Updated on 12/16/2010

If you make a slight change in step 3 above you can have this workflow add not only audio files but even entire folders to iTunes and better yet, iTunes will ask if you want to replace existing files so that you don’t end up with duplicate files in your iTunes library. This is great.

So what do you have to do? Instead of audio files, select files or folders. Just this. Save the workflow. Now right click over any folder in Finder and you’ll see that you get a new menu option under Services called Add to iTunes.

Add to iTunes context menu option in Finder when right clicking a folderFigure 4 - Add to iTunes context menu option in Finder when right clicking a folder

Notes
Service workflows are saved in /Users/YourUserName/Library/Services.

In prior versions of Mac OS, there was an option to save the workflow as a plug-in. This was necessary so that you could have a context menu option (right-click) in Finder to run the workflow. I tried to go this way but this option isn’t available in Mac OS X 10.6.4. I realized that I had to create a Service workflow when I read this question at Apple’s Support site: No Automator plug-in in 10.6?

Download
You can download this workflow at:
https://sites.google.com/site/leniel/blog/AddtoiTunes.workflow.zip

References
Automator - Your Personal Automation Assistant

Automator - Learn by example

Automator at Apple’s Mac OS – All Applications and Utilities

Automator article at Wikipedia

Automate the download of a list of URLs/links

I just wanted to automate the process of downloading a list of URLs/links. I thought about asking a question at SuperUser. So I did that and got a few answers. One of those answers pointed to the piece of software that does exactly what I wanted. The software is a Firefox add-on that I had used a long time ago but couldn’t think about it for this task. Its name is DownThemAll!. Yes with an exclamation mark at the end. I think this has to do with a relief felling you feel when you’re using it.

In this post I’ll walk you through the steps necessary to get your downloads going in a really fast way (fasten your seat belt). No more downloading and saving file by file. Phew!

I’m going to use the same list of URLs I posted on my question at SuperUser.

Suppose you have a list of URLs as this one:

http://creamteam.tv/wp-content/uploads/2010/06/10-Chinatown.mp3
http://mp3muffin.com/train/burbs.mp3
http://www.knoxroad.com/wp-content/music/May/01%20World%20Sick.mp3
http://indierockcafe.com/mp3s/2010/may/5-18/bandofhorses_factory1.mp3
http://www.strangefamousrecords.com/sfr-audio/_common/sagefrancis_slowman.mp3
http://dangerbirdrecords.com/public/theoneamradio/crediblethreats.mp3
http://www.beggarsgroupusa.com/mp3/HolyFuck_LatinAmerica.mp3
http://dl.dropbox.com/u/4746099/05%20Choices%201.mp3
http://subpop-public.s3.amazonaws.com/assets/audio/6801.mp3
http://gvsbchris.com/01%20Sleep%20Paralysist.mp3
http://bantermm.com/tracks/Annuals-Loxtep.mp3
http://downloads.pitchforkmedia.com/The%20National%20-%20Bloodbuzz%20Ohio.mp3
http://stereogum.com/mp3/the%20morning%20benders%20-%20Excuses.mp3

Save this list in a text file [ .txt ] extension and name it MP3s.txt.

Now let’s get DownThemAll! and do the real thing…

1 - Install DownThemAll! add-on for Firefox. After installing restart Firefox.

2 - Go to Firefox menu and select Tools - DownThemAll! Tools - Manager... Right-click inside DownThemAll! screen.

3 - Select context menu Misc - Import from file.

4 - On Import downloads dialog window make sure you select Text Files in the dropdown list.

5 - Point to the text file MP3s.txt that contains the URLs. Click Open button.

6 - On Make your selection dialog window, DownThemAll! will load each link it finds in the text file allowing you to select which ones you want to download and the folder where you want the files to be saved as well.

7 - Make your selections, click Start button.

Here's a screenshot of it just doing the "Downloading" part:

DownThemAll! downloading the list of URLs from my question at SuperUser
Figure 1 - DownThemAll! downloading the list of URLs from my question at SuperUser

Oh… and this is the feature request on DownThemAll! trac opened 3 years ago.

Nice to see this implemented and working so well.

Congrats to DownThemAll! developers and users. Fantastic add-on.