OpenXml: Add image to presentation

With the following code snippet, a image can be added to a presentation PPTX. The code is not nice but serves as a working example.

public static void AddImage(string file, string image)
{
    using (var presentation = PresentationDocument.Open(file, true))
    {
        var slidePart = presentation
            .PresentationPart
            .SlideParts
            .First();

        var part = slidePart
            .AddImagePart(ImagePartType.Png);

        using (var stream = File.OpenRead(image))
        {
            part.FeedData(stream);
        }

        var tree = slidePart
            .Slide
            .Descendants<DocumentFormat.OpenXml.Presentation.ShapeTree>()
            .First();

        var picture = new DocumentFormat.OpenXml.Presentation.Picture();

        picture.NonVisualPictureProperties = new DocumentFormat.OpenXml.Presentation.NonVisualPictureProperties();
        picture.NonVisualPictureProperties.Append(new DocumentFormat.OpenXml.Presentation.NonVisualDrawingProperties
        {
            Name = "My Shape",
            Id = (UInt32)tree.ChildElements.Count - 1
        });

        var nonVisualPictureDrawingProperties = new DocumentFormat.OpenXml.Presentation.NonVisualPictureDrawingProperties();
        nonVisualPictureDrawingProperties.Append(new DocumentFormat.OpenXml.Drawing.PictureLocks()
        {
            NoChangeAspect = true
        });
        picture.NonVisualPictureProperties.Append(nonVisualPictureDrawingProperties);
        picture.NonVisualPictureProperties.Append(new DocumentFormat.OpenXml.Presentation.ApplicationNonVisualDrawingProperties());

        var blipFill = new DocumentFormat.OpenXml.Presentation.BlipFill();
        var blip1 = new DocumentFormat.OpenXml.Drawing.Blip()
        {
            Embed = slidePart.GetIdOfPart(part)
        };
        var blipExtensionList1 = new DocumentFormat.OpenXml.Drawing.BlipExtensionList();
        var blipExtension1 = new DocumentFormat.OpenXml.Drawing.BlipExtension()
        {
            Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}"
        };
        var useLocalDpi1 = new DocumentFormat.OpenXml.Office2010.Drawing.UseLocalDpi()
        {
            Val = false
        };
        useLocalDpi1.AddNamespaceDeclaration("a14", "http://schemas.microsoft.com/office/drawing/2010/main");
        blipExtension1.Append(useLocalDpi1);
        blipExtensionList1.Append(blipExtension1);
        blip1.Append(blipExtensionList1);
        var stretch = new DocumentFormat.OpenXml.Drawing.Stretch();
        stretch.Append(new DocumentFormat.OpenXml.Drawing.FillRectangle());
        blipFill.Append(blip1);
        blipFill.Append(stretch);
        picture.Append(blipFill);

        picture.ShapeProperties = new DocumentFormat.OpenXml.Presentation.ShapeProperties();
        picture.ShapeProperties.Transform2D = new DocumentFormat.OpenXml.Drawing.Transform2D();
        picture.ShapeProperties.Transform2D.Append(new DocumentFormat.OpenXml.Drawing.Offset
        {
            X = 0,
            Y = 0,
        });
        picture.ShapeProperties.Transform2D.Append(new DocumentFormat.OpenXml.Drawing.Extents
        {
            Cx = 1000000,
            Cy = 1000000,
        });
        picture.ShapeProperties.Append(new DocumentFormat.OpenXml.Drawing.PresetGeometry
        {
            Preset = DocumentFormat.OpenXml.Drawing.ShapeTypeValues.Rectangle
        });

        tree.Append(picture);
    }
}

OpenXml: Add shape to presentation

Following snippet loads a presentation using the OpenXml SDK and adds a simple rectangular shape to the first slide.

public static void AddShape(string file)
{
    using (var presentation = PresentationDocument.Open(file, true))
    {
        var tree = presentation
            .PresentationPart
            .SlideParts
            .ElementAt(0)
            .Slide
            .Descendants<DocumentFormat.OpenXml.Presentation.ShapeTree>()
            .First();

        var shape = new DocumentFormat.OpenXml.Presentation.Shape();

        shape.NonVisualShapeProperties = new DocumentFormat.OpenXml.Presentation.NonVisualShapeProperties();
        shape.NonVisualShapeProperties.Append(new DocumentFormat.OpenXml.Presentation.NonVisualDrawingProperties
        {
            Name = "My Shape",
            Id = (UInt32)tree.ChildElements.Count - 1
        });
        shape.NonVisualShapeProperties.Append(new DocumentFormat.OpenXml.Presentation.NonVisualShapeDrawingProperties());
        shape.NonVisualShapeProperties.Append(new DocumentFormat.OpenXml.Presentation.ApplicationNonVisualDrawingProperties());

        shape.ShapeProperties = new DocumentFormat.OpenXml.Presentation.ShapeProperties();
        shape.ShapeProperties.Transform2D = new DocumentFormat.OpenXml.Drawing.Transform2D();
        shape.ShapeProperties.Transform2D.Append(new DocumentFormat.OpenXml.Drawing.Offset
        {
            X = 0,
            Y = 0,
        });
        shape.ShapeProperties.Transform2D.Append(new DocumentFormat.OpenXml.Drawing.Extents
        {
            Cx = 1000000,
            Cy = 1000000,
        });
        shape.ShapeProperties.Append(new PresetGeometry
        {
            Preset = ShapeTypeValues.Rectangle
        });
        shape.ShapeProperties.Append(new SolidFill
        {
            SchemeColor = new SchemeColor
            {
                Val = SchemeColorValues.Accent2
            }
        });
        shape.ShapeProperties.Append(new Outline(new NoFill()));

        tree.AppendChild(shape);
    }
}

OpenXml: Units of measurement

Ever wondered what that coordinate system in OpenXml is? It’s fixed point arithmetic based long (64bit). It is optimized for fitting both inch and metric base. Office Interop uses DPI based floating point instead. Here some code to convert. But beware: It’s optimized for code-less and not for rounding errors!

    public static class EMU
    {
        // 20.1.2.1 EMU Unit of Measurement
        //
        // 1 EMU = 1 / 914400 US inch = 1 / 360000 cm
        //
        public static float EmuToDpi(this long value)
        {
            return (float)((double)value / 12700.0);
        }
        public static long DpiToEmu(this float value)
        {
            return (long)(value * 12700.0f);
        }
    }

OpenXml: Loading a PowerPoint presentation with C# and OpenXml

OpenXml is the open source library to load and modify Microsoft Office documents without the need of Office.

In this example, I want to open a presentation, iterate over all shapes and print their shape name.

First, I create a C# console application inside Visual Studio. Then I load the OpenXml package from the nu-get console:

Install-Package DocumentFormat.OpenXml

The example application is a console application that opens the presentation provided through command line argument. Then it iterates over all shapes and prints their name to console:

using DocumentFormat.OpenXml.Packaging;
using System;
using System.Linq;

namespace OpenXML1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var presentation = PresentationDocument.Open(args[0], false))
            {
                foreach (var shape in presentation
                    .PresentationPart
                    .SlideParts
                    .Select(p => p.Slide)
                    .SelectMany(s => s
                        .Descendants<DocumentFormat.OpenXml.Presentation.Shape>()))
                {
                    Console.WriteLine(shape
                        .NonVisualShapeProperties
                        .NonVisualDrawingProperties
                        .Name);
                }
            }
        }
    }
}

Learning RESTful with ASP.NET WebAPi

As Wikipedia states, REST means Representation State Transfer and is a definition for providing interoperability between webservices. Requests are made to a URI. The response is most of the time JSON but can also be XML or HTML.

The constraints are:

  • Client-Server: Separation between representation (client) and storage (server).
  • Stateless: The server does not store state for clients. All state must be stored on client and provided again with each request to the server.
  • Cacheable: The request and response should be cacheable in a key-value store.
  • Layered system: The client may connected to one of many servers, e.g. behind a load balancer. It is not transparent to the client if the response was cached or calculated.
  • Code on demand (optional): Servers can return executable code (Java Applets, JavaScript) which will  be executed on the client
  • Uniform interface: The fundamental constraint of a REST service.
    • Identification of resource: The returned resource may not be on the internal format of the server and instead JSON etc.
    • Manipulation by client: Client can delete and modify the resource just with its representation.
    • Selfdescriptive: Messages should contain enough information on how to process them
    • Hypermedia

Now let’s get physical with Visual Studio 2015.

Create a new project in Visual Studio

2016-11-18-19_07_10-your-asp-net-application-microsoft-visual-studio

2016-11-18 19_07_27-Your ASP.NET application - Microsoft Visual Studio.png

Add controller

2016-11-18-19_11_32-rest2-microsoft-visual-studio

2016-11-18 19_11_49-REST2 - Microsoft Visual Studio.png

2016-11-18-19_12_36-rest2-microsoft-visual-studio

Test

Press F5 to start debugging. A browser should open. Then append the following to the url:

2016-11-18-19_11_14-localhost-and-12-more-pages-%e2%80%8e-microsoft-edge

This should call the get method inside the ModelController which returns nicely formatted JSON dummy values.

GET/PUT/POST/DELETE

Now let’s implement the basic operations of a RESTful API. It’s basically four methods:

  • GET: Returns a resource for a given ID
  • POST: Adds a given resource
  • PUT: Updates the given resource
  • DELETE: Deletes a given resource

The basic storage is a static list of strings. This is not thread-safe nor very smart but serves the demonstration purpose:

    public class ModelController : ApiController
    {
        [HttpGet]
        [Route("")]
        public IEnumerable Get()
        {
            return VALUES;
        }

        [HttpGet]
        [Route("{id}")]
        public string Get(int id)
        {
            return VALUES[id];
        }

        [HttpPost]
        [Route("")]
        public void Post([FromBody]string value)
        {
            VALUES.Add(value);
        }

        [HttpPut]
        [Route("{id}")]
        public void Put(int id, [FromBody]string value)
        {
            VALUES[id] = value;
        }

        [HttpDelete]
        [Route("{id}")]
        public void Delete(int id)
        {
            VALUES.RemoveAt(id);
        }

        private static List VALUES = new List();
    }

2016-11-19-09_21_46-rest3-running-microsoft-visual-studio

Using curl, we can now post, get, put and delete values on the server:

    curl -H "Content-Type: application/json" -X GET "http://localhost:56293/0"
    curl -H "Content-Type: application/json" -X POST -d "'hello'" "http://localhost:56293/"
    curl -H "Content-Type: application/json" -X PUT -d "'hello 2'" "http://localhost:56293/0"
    curl -H "Content-Type: application/json" -X DELETE "http://localhost:56293/0"

Resources

Admin: Small network with OpenWRT and Windows Domain Controller

We have a OpenWRT router, Microsoft Windows Server 2012 R2 (Domain Controller & DNS server role) and about 10 clients. To get the clients connected to the domain controller, the easiest is to set the DNS server on all clients to the Windows Server via DHCP:

  • Domain controller gets a static IP
  • Clients get IP and DNS settings by DHCP

This can be easily achieved through the web interface of OpenWRT:

  • Network > Interfaces > Edit > DHCP Server > Advanced Settings > DHCP-Options you have to enter “6,IP_OF_DOMAIN_CONTROLLER”

 

2016-11-17-15_21_52-openwrt-interfaces-luci-and-12-more-pages-%e2%80%8e-microsoft-edge

In the OpenWRT UI you can insert the DHCP options that tell clients the DNS to use

2016-11-18-09_12_24-192-168-178-1-putty

When connecting to the router you can verify the DNS servers were inserted

 

Learning DocumentDB in 30 minutes

DocumentDB seems Microsoft’s big answer on CouchDB and MongoDB. It’s a schema free database for JSON documents providing a SQL interface at large scale, Azure hosted and SSD backed.

A DocumentDB database has collections which contain the actual JSON documents. The collection can have stored procedures, triggers and user-defined-functions. All have to be written in JavaScript.

The database interface is a RESTful API accepting GET, PUT, POST and DELETE requests. On top of that there’re wrapper for different programming languages.

The query language is an extended subset of SQL. Unfortunately it has the same drawbacks like the competitors: There is no inter-document or inter-collection join (at the time of writing). So its crucial to keep the document’s denormalized.

At its core, DocumentDB is scalable and reliable at the same time. It allows different models to propagate writes to all copies of the data, fitting different use-cases.

Resources: