Convert Microsoft PowerPoint Presentation to a Video Using C# .NET and Hosting Tips (IIS)

Development

We will need following References for the project

Microsoft.Office.Core;
Microsoft.Office.Interop.Graph;
System.Runtime.InteropServices;
Microsoft.Office.Interop.PowerPoint;
System.IO;

Method for the video conversion

public string makeVideo()
{
  string videoFilePath = "\videoName.wmv", presentationPath = "\yourPresentation.pptx";
  try
  {
    Microsoft.Office.Interop.PowerPoint.Application ppApp = new Microsoft.Office.Interop.PowerPoint.Application();
    Microsoft.Office.Interop.PowerPoint.Presentations oPresSet = ppApp.Presentations;
    Microsoft.Office.Interop.PowerPoint._Presentation oPres = oPresSet.Open(
      presentationPath,
      MsoTriState.msoFalse,
      MsoTriState.msoFalse,
      MsoTriState.msoFalse);
    System.Threading.Thread.Sleep(180);
    oPres.UpdateLinks();
    try
    {
      oPres.UpdateLinks();

      //CreateVideo(string FileName, bool UseTimingsAndNarrations, int DefaultSlideDuration, int VertResolution, int FramesPerSecond, int Quality)
      oPres.CreateVideo(videoFilePath, true, 5, videoModel.size, 30, 85);

     while (oPres.CreateVideoStatus == Microsoft.Office.Interop.PowerPoint.PpMediaTaskStatus.ppMediaTaskStatusInProgress || oPres.CreateVideoStatus == Microsoft.Office.Interop.PowerPoint.PpMediaTaskStatus.ppMediaTaskStatusQueued)
     {
        System.Threading.Thread.Sleep(10000);
     }
  return "Video is Created !!";
  }
  catch (Exception er)
  {
    string error = er.StackTrace.ToString();
    return error;
  }

  finally
  {
   oPres.Close();
   ppApp.Quit();
   GC.Collect();
  }
  }
  catch (Exception err)
  {
    string error2 = err.ToString();
    return error2;
  }
}

Now your PowerPoint presentation to video program is ready.

Hosting

When you host this in IIS there are few configurations to be done.  Otherwise you will get an error exception something like below.

System.UnauthorizedAccessException: Retrieving the COM class factory for component with CLSID {91493441-5A91-11CF-8700-00AA0060263B} failed due to the following error: 80070005 Access is denied.

Followings are the configurations to avoid that error.

  1. Create a user in Admin group (i e: powerpointUser) (You can also use an existing user).
  2. set Password Never Expire and Password Cannot Be change for this user.
  3. Go to Control Panel  >> Administrative Tools >> Component Services >> Computers >> My Computer >> DCOM Config.
  4. Select Microsoft Word 97 – 2003 Document and right click and open Properties.
  5. In General tab set Authentication Level : None.
  6. In Security tab Customize all 3 permissions and add Everyone user by clicking the Edit button.
  7. In Identity tab select “This User” add details for the user created in first step. (powerpointUser).
  8.  Click Apply and Ok.
  9. Do the above 5,6,7,8 steps to the Microsoft PowerPoint Application and Microsoft PowerPoint Slide too in the DCOM Config.
  10. Host your website in the IIS and add the user created in first step (powerpointUser) to the website. (right click on the website in IIS and select “Edit Permissions…”. You can add the user in Security tab)

Now your program should work fine after hosting in IIS.

 

Adding Options for Custom Visuals – Microsoft Power BI

This article shows how to add a flip button and a text field as custom options in Power BI custom visuals.

  1. First we need to define options that we are going to add, in our custom visual’s capabilities.
    public static capabilities: VisualCapabilities = {
     objects: {
       flipButton: {
         displayName: 'Flip Button',
         properties: {
         button: {
         type: { bool: true },
         displayName: 'Button'
         }
         }
       },
       textField: {
         displayName: 'Text Field',
         properties: {
         text: {
         type: { text: 'Default Text' },
         displayName: 'Text'
         }
         }
       }
      }
    
    
    }
  2. After defining options, enumerateObjectInstances() method should be included in our code.  enumerateObjectInstances is used by the Power BI app to populate the format pane of the visual.
    public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {
    
      var enumeration = new ObjectEnumerationBuilder();
      var instances: VisualObjectInstance[] = [];
    
      switch (options.objectName) {
        case 'flipButton':
        enumeration.pushInstance({
        objectName: 'flipButton',
        selector: null,
        properties: {
        button: this.getFlipButtonStatus()
        },
        });
        break;
        case 'textField':
        enumeration.pushInstance({
        objectName: 'textField',
        selector: null,
        properties: {
        text: this.getText()
        },
        });
        break;
        }
       return enumeration.complete();
     }
  3. Finally the values for above options should be derived using getFlipButtonStatus() and getText() methods. For theses methods we need to set the dataView to a variable inside the update method. //this.dataView = options.dataViews[0];
    private getFlipButtonStatus() {
       var buttonStatus = false;
       if (this.dataView) {
         if (this.dataView.metadata.objects) {
           var flipButtonObj = this.dataView.metadata.objects.flipButton;
           if (flipButtonObj) {
              buttonStatus = flipButtonObj.button;
            }
          }
       }
       return buttonStatus;
     }
    
    private getText() {
       var defaultText = "Default Text";
       if (this.dataView) {
         if (this.dataView.metadata.objects) {
           var textObj = this.dataView.metadata.objects.textField;
           if (textObj) {
             defaultText = textObj.text;
           }
         }
       }
       return defaultText;
     }

    flippp

  4. Then compile the code and use it in the Power BI. Custom options should be shown in  the format panel as above.

Socket programming in Node.js

We will mainly talk about three things in this socket programming in Node.js article.

  • Create Node.js server
  • Socket connection
  • Send data through socket

Creating the server
First create the package.json file using below command.

npm init

For this application we need to include “socket.io” and “express”.
here is our server.js

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

http.listen(4400, '0.0.0.0', function () {
console.log('listening on *:4400');
});

Below commands are used to install “express” and “socket.io”.

npm install express --save
npm install socket.io --save

The Node.js server is created. We can start the server using below command.

node server.js

We can access it on http://localhost:4400/

Writing the socket connection

We can identify connected/disconnected sockets to our sever by adding below code to our server.js.

io.on('connection', function (socket) {
console.log('socket: '+ socket.id +' connected.');

socket.on('disconnect', function () {
console.log('socket: '+ socket.id +' disconnected.');
});
});

Sending Data

-From the client side to the server

Client Side

Lets name the event as ‘client message’.

var socket = io();
var message = "This is the message from client side";
socket.emit('client message', message);

Server Side

io.on('connection', function(socket){
  socket.on('client message', function(message){
    console.log('message: ' + message);
  });
});

 

-From the server to client

Server Side

Lets name the event as ‘server message’;

var message = 'This is the message from server side';

io.on('connection', function(socket){
    io.emit('server message', msg);
});

Client Side

  socket.on('server message', function(message){
    console.log('message: '+ message);
  });

D3 charts with AngularJS

There are many ways to draw D3 graphs with AngularJS framework. This post will show you one of the simplest ways to do it. Below are the steps for draw a D3 path by creating an Angular Directive.

  • Create Angular Directive
(function () {
 'use strict';
angular.module('exampleAngular.directives')
 .directive('d3Path', [function () {
 return {
  restrict: 'EA',
  scope: {
  ready: '=',
  valueAccessor: '='
  },
 link: function (scope, iElement) {
  var chart;
  d3.select(iElement[0]).append('svg').attr({
  'id': 'path-container',
  'width': 200,
  'height': 200
 })
 .append('g').attr( {'transform':'translate(0,5)'});
 scope.$watch('ready', function (newVals) {
   return scope.render(newVals);
 }, true);

// define render function
 scope.render = function (ready) {
  if (ready) {
    chart = new D3Path(scope.valueAccessor(),
                'path-container'); 
   } 
   }; 
   } 
   }; 
 }]); 
}())

// function for draw D3 path
function D3Path(value, containerId) {
 var self = this, path, pathData = value, totalLength;
 options = {
 lineFunction: d3.svg.line()
 .x(function (d) { return d.x; })
 .y(function (d) { return d.y; })
 .interpolate('linear')
 };

 self.chart = function () {
 path = d3.select('#' + containerId).select('g').append('path')
 .attr('d', options.lineFunction(pathData))
 .attr('stroke','#ff0000')
 .attr('stroke-width', 2)
 .attr('fill', 'none');

 totalLength = path.node().getTotalLength();

 path
 .attr('stroke-dasharray', totalLength + " " + totalLength)
 .attr('stroke-dashoffset', totalLength)
 .transition()
 .duration(1000)
 .ease('linear')
 .attr('stroke-dashoffset', 0);

 return self;
 };

 return self.chart();
};
  • include the element in html page

Capture

  •  Feed data through exampleControler.js
(function () {
 'use strict';

 angular.module('exampleAngular.controllers')
 .controller('exampleController', ['$scope', 
function ($scope) {
 var vm = this;
 vm.dataReady = function () {
        reurn true;
 };
 vm.valueAccessor = getPathData;

function getPathData() {
var lineData = [{ "x": 1, "y": Math.random() * 100 }, 
      { "x": 20, "y": Math.random() * 100 },
      { "x": 40, "y": Math.random() * 100 }, 
      { "x": 60, "y": Math.random() * 100 },
      { "x": 80, "y": Math.random() * 100 }, 
      { "x": 100, "y": Math.random() * 100 },
      { "x": 120, "y": Math.random() * 100 }
      ]

 return lineData;
}

 }]);
}());
  • application.js
(function () {
angular.module('exampleAngular', [
'exampleAngular.services',
'exampleAngular.controllers',
'exampleAngular.directives']);

angular.module('exampleAngular.services', []);
angular.module('exampleAngular.controllers', []);
angular.module('exampleAngular.directives', []);
}());

Animations In D3.js

Animation plays a vital role in interactive data visualization. It is really helpful to

  • give feedback to users
  • show, how data goes from one state to another.
  • show any form of real-time data

D3 has lots of possibilities for data animation and they are really easy to implement. In D3 mostly animations are  done using “transitions”. Here one or more characteristics of an object would transition from one value to another. It is simple like, when you update the position of an item smoothly over time, it animates. Not only the position we can also update size and color of an item too.

D3 Transition

D3’s selection.transition method makes it easy to animate transitions when changing the DOM.

d3.select("body").transition()
                 .style("color", "red");

Transitions are are pre-element and exclusive

– Each element transitions independently. When you create a transition from a selection, think of it as a set of transitions. Transitions happen one per element rather than a single mega-transition running on multiple elements (pre-element).

– Only one transition can be running on the element at the same time. Starting a new transition on the element stops any transition that is already running (exclusive).

Simple Uses of Transition

//color change example
d3.select("body")
  .style("color", "green") // make the body green
  .transition()
  .style("color", "red"); // then transition to red

//position change example
d3.select(“element")
  .transition()
  .attr("x",320);

After using the transition() method, it’s possible to specify a value for duration and delay. Duration is the number of milliseconds the transition will last, while delay is the number of milliseconds the system will wait before launching it.

Take a look at below live examples.

Slow transition (larger duration): http://jsfiddle.net/Chathunga/L2gywcvd/

Fast transition (smaller duration):http://jsfiddle.net/Chathunga/ypxcmhud/

Double Transition

element.transition()
  .attr("x",320);
element.transition()
  .attr("y",200);

It seems like above code sample will move the element right, then down. But it will not happen like that. What actually will happen is this will start to move the element right, then fire the second transition which will move it down. But the both transitions have same duration and they have no delay. Therefore only last transition will have a visible effect. We can resolve this using a delay. But unfortunately we don’t know the duration time of these transitions because we didn’t define the duration for these transitions. Therefore in that case we use following syntax to chain two or more transitions. In here the syntax starts another event exactly at the end of a transition.

element
   .transition()
   ...
   .each("end", function() { ... });

Live example:

http://jsfiddle.net/Chathunga/y9k37tq7/1/

Life of a Transition

Transitions have a four-phase life cycle.

  • Schedule – A transition is scheduled when it is created. when you call selection.transition, you are scheduling a transition.
  • Start – A transition starts according to its delay, which was specified when the transition was scheduled.If no delay was specified, then the transition starts as soon as possible
  • Run – While the transition runs, its tweens are repeatedly invoked with values of t ranging from 0 to 1.
  • End – The ending time is always exactly 1 so that the ending value is set exactly when the transition ends.

This is only a rough and simple description on D3 animation and transition. In D3 animations .tween, .interpolate and D3 timer methods are also used and those are  bit complex methods.

An Animated Trend Line With D3

D3 provides a simple and easy way to create a trend line in your website. This line is created using SVG paths and we can apply various line styles (straight, cardinal spline, closed line) according to situations. We need to have a sequence of x,y coordinates to represents one line.  SVG uses SVG Path Mini-Language to draw paths. Therefore we need set of  SVG Path Mini-Language codes to draw a line for given coordinates. This is where the D3 helps us. D3.js provides a Path Data Generator Function for lines.

d3.svg.line()

What above function basically do is take data and convert it into the SVG Path Mini-Language. In order to do this we should define an accessor function to return the x,y coordinates from our data.

var lineCreator = d3.svg.line()
                   .x(function(d) { return d.x; })
                   .y(function(d) { return d.y; })
                   .interpolate("linear");

We can use “linear”, “step-before”, “step-after”, “basis”, “basis-open”, “basis-closed”, “bundle”, “cardinal”, “cardinal-open”, “cardinal-closed”, “monotone” as interpolate options. For a smoother line we can use the “cardinal” option.

Scaling Coordinates :

var lineCoordinates = [ { "x": 1,   "y": 20},  
                        { "x": 20,  "y": 50},
                        { "x": 40,  "y": 40}, 
                        { "x": 60,  "y": 20},
                        { "x": 80,  "y": 100}];

Important: In SVG (0,0) coordinate  is at the top left corner. But generally in line graphs the (0,0) coordinate is at the bottom left corner. Therefore we need to convert above coordinates according to SVG scale (SVG size and 0,0 top left corner).

Scaling according to the SVG size: We can use D3 scales for this. Lets say our SVG height is 50px. But we have our y coordinate up to 100px. So we need to get all y coordinates within [0,50] range.

var yScale = d3.scale.linear()
                       .range([0, 50])
                       .domain([minY, maxY]);

Convert Y coordinates to begin from top (According to SVG 0,0 at top left coner): For example, our actual Y coordinate is 50px from the bottom of SVG. But in SVG it takes as 50px from the top of the SVG. We can use below method  to scales all Y coordinates to fit for SVG height (50 px) and convert all Y coordinates to begin from top.

var yScale = d3.scale.linear()
            .range([50, 0]) // convert y coordinate
            .domain([minY, maxY]);

Output from above method:

yScale(0) = 50

yScale(50) = 0

Example:

html

<script src="http://d3js.org/d3.v3.min.js"></script>

<div class="container">
 <svg id="path" width="100" height="50"></svg>
</div>

JavaScript

// Scale for Y coordinate
var yScale = d3.scale.linear()
     .range([50, 0])
     .domain([0, 100]);

// Scaled coordinates 
var lineCoordinates = [{ "x": 1, "y": yScale(20)}, 
                       { "x": 20, "y": yScale(50)},
                       { "x": 40, "y": yScale(40)},
                       { "x": 60, "y": yScale(20)},
                       { "x": 80, "y": yScale(100)}];

// Function for the path
var lineCreator = d3.svg.line()
                  .x(function(d) { return d.x; })
                  .y(function(d) { return d.y; })
                  .interpolate("linear");

// Draw Line
var path = d3.select("#path")
 .append("g").attr({ "transform": "translate(0,5)" })
 .append("path")
 .attr("d", lineCreator(lineCoordinates))
 .attr("stroke", "red")
 .attr("stroke-width", 2)
 .attr("fill", "none");

// Animation
var totalLength = path.node().getTotalLength();

path
 .attr("stroke-dasharray", totalLength + " " + totalLength)
 .attr("stroke-dashoffset", totalLength)
 .transition()
 .duration(1000)
 .ease("linear")
 .attr("stroke-dashoffset", 0);

Live Example : https://jsfiddle.net/Chathunga/6564580h/5/