2011-09-27

Microsoft Word Macro: Convert Word-files to PDF-files

Microsoft Word Macro

This post comes out of me helping a colleague with a quick macro, for Microsoft Office Word, that he needed to speed up service towards a customer.

I simply recorded a macro while converting one Word-file into a PDF-file and then Googled for some code to access files on disc and put it all together in a loop.

Sub ConvertWordsToPdfs()

    Dim directory As String    
    directory = "C:\Wordup"
  
    Dim fso, newFile, folder, files
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    Set folder = fso.GetFolder(directory)
    Set files = folder.files
    
    For Each file In files

        Dim newName As String
        newName = Replace(file.Path, ".doc", ".pdf")
                
        Documents.Open FileName:=file.Path, _
            ConfirmConversions:=False, ReadOnly:=False, AddToRecentFiles:=False, _
            PasswordDocument:="", PasswordTemplate:="", Revert:=False, _
            WritePasswordDocument:="", WritePasswordTemplate:="", Format:= _
            wdOpenFormatAuto, XMLTransform:=""
            
        ActiveDocument.ExportAsFixedFormat OutputFileName:=newName, _
            ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
            wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=1, To:=1, _
            Item:=wdExportDocumentContent, IncludeDocProps:=True, KeepIRM:=True, _
            CreateBookmarks:=wdExportCreateNoBookmarks, DocStructureTags:=True, _
            BitmapMissingFonts:=True, UseISO19005_1:=False
        
        ActiveDocument.Close
      
    Next

End Sub

I guess I won't update or tune this macro a lot, but you can find this macro as a Github Gist as well.

2011-05-18

Add Facebook Like, Twitter Tweet and Other Social Links to Your Blog

If you want people to be able to quickly and easily link to your blog-posts or pages in general you can take some shortcuts to get that functionality by using AddThis.

There are several ways to include buttons from AddThis to your page, but for standard functionality with a good overview I would say point to using regular HTML with some automatic JavaScript-magic happening in the background.

The basic code looks like this:

<div class="addthis_toolbox addthis_default_style">
    <a class="addthis_button_facebook"></a>
    <a class="addthis_button_tweet"></a>
    <a class="addthis_button_email"></a>
</div>

There is a very well documented and detailed API Reference on AddThis' website.

Customizing

There are some additional classes you can add to the link-tags to make specialized customization to the buttons. If you add addthis_32x32_style the icon will become larger and stick out more. It could be used on the more popular social sharing services.

<div class="addthis_toolbox addthis_default_style">
    <a class="addthis_button_facebook addthis_32x32_style"></a>
    <a class="addthis_button_twitter addthis_32x32_style"></a>
    <a class="addthis_button_digg addthis_32x32_style"></a>
    <a class="addthis_button_delicious addthis_32x32_style"></a>
    <a class="addthis_button_google"></a>
    <a class="addthis_button_googlebuzz"></a>
    <a class="addthis_button_blogger"></a>
    <a class="addthis_button_tumblr"></a>
    <a class="addthis_button_posterous"></a>
</div>

Which produces a result that looks like this:

With this code Facebook, Twitter, Digg and Delicious are twice the size of the other ones.

AddThis has an extremely long list of supported sharing services supported.

2011-04-27

Language Localization with Google Maps API

Google Maps

When you include a Google Maps to your website via the Google Maps JavaScript API uses the browser's set preferred language to display the texts. Sometimes this doesn't turned out as planned and you want to be able to override this with your own choice.

Changing language is done with an additional argument when referencing the script-file. The argument used is language.

<script type="text/javascript"
    src="http://maps.google.com/maps/api/js?sensor=false&language=ja">

There is of course a reference to the supported languages and their language codes.

Region Localization

To set the language of the names of the countries, cities and other places, you can use the Region Localization.

2011-04-18

Javascript: Timeout on a Textbox using jQuery

jQuery

Here is a quick post about how to use a JavaScript-timer to only execute a textbox's functionality after a certain amount of time.

Worth noticing in the code is that we handle a key-press on the Enter-button instantly, while otherwise we only execute the functionality after the user left the keyboard alone for 0,5 seconds.

var filterTimeoutId = 0;

var textboxFunction = function() {
   // The function the textbox should perform
};

$('input#TextBox').keypress(function (e) {
    if (e.which === 13) { // Enter-key
        e.preventDefault(); // Prevent page postback
        clearTimeout(filterTimeoutId);

        textboxFunction();
        return;
    }

    clearTimeout(filterTimeoutId);
    var timeout = 500; // Timeout in milliseconds
    filterTimeoutId = setTimeout(textboxFunction, timeout);
});

2010-09-08

Visual Studio 2010: Dropped Assembly References Workaround

After adding some references to external assemblies like to NLog or Munq I found out that on some projects Visual Studio 2010 had a tendency to drop the reference to some of these assemblies.

After the usual searching of Google and Stackoverflow I've put together a combination of different solutions that seems to solve this issue.

  • Step 1: Expand your references and bring up the properties-window. Set Specific Version to True:
  • Step 2: Right click on the project and click Untload Project:
  • Step 3: Right click again on the project and click Edit ...csproject.
  • Step 4: Add an XML-element with the name SpecificVersion with the value True beneath the reference in question:
  • Step 5: Right click on the project and click Reload Project.

This works for me so far.

2010-09-01

Conditional Scrolling Banner with YUI

I was in need of a banner that would scroll along on the page, even when the user had scrolled passed it. After Googling with Bing for any done JavaScript to achieve this, I still only found plug-ins for different PHP-based CMS:es.

After spending almost as much time searching for something already built as it would have taken to build it, I did just that, I took matters into my own hands.

In my case I solved it with Yahoo's YUI 2, but you can do it just as well in any other Javascript-library, like jQuery.

<!-- Static banners above conditional scrolling one -->
<div id="scrollBanner" class="scrollBanner">
<!-- Image and/or flash-banners -->
<img src="Banner.gif" alt="Banner" />
</div>

What we need to do is to find the element to scroll in the DOM and find it's initial Y-position. Then we add a listener to the scroll-event and just flip the CSS-class of the element, depending if we've scrolled past it or not.

var scrollBanner = document.getElementById("scrollBanner");
// Initial banner Y-position
var bannerYPos = YAHOO.util.Dom.getY(scrollBanner);

YAHOO.util.Event.addListener(window, 'scroll',
    function() {
        var isBannerAboveScrollTop = (YAHOO.util.Dom.getDocumentScrollTop() > bannerYPos);
        var oldClassName = isBannerAboveScrollTop ? "scrollBanner" : "scrollBanner_fixed";
        var newClassName = isBannerAboveScrollTop ? "scrollBanner_fixed" : "scrollBanner";
        YAHOO.util.Dom.replaceClass(scrollBanner, oldClassName, newClassName);
    }
);

Just style your scrollingBanner_fixed-class with a fixed position and the width you want it to have. Adjust the top-setting to set how high up on the screen the scrolling banner should be. You could also use padding to make the scrolling-experience more smooth.

.scrollingBanner_fixed {
    position: fixed;
    top: 0px;
    width: 100px;
}

This code could of course also be used for good, to have some kind of toolbar that would scroll along on a page.

2010-08-04

Guidelines for URI Design

Jacob Gillespie has worked on a post concerning URL Guidelines, that underwent much revision and was posted as a guest post on CSS-Tricks named Guidelines for URI Design.

Clean URIs are one component of a clean website, and it is an important one. The majority of end-user access to the Internet involves a URI, and whether or not the user actually enters the URI, they are working with one nonetheless.

Here is an outtake of the general principles of the article:

  • A URI must represent an object, uniquely and permanently - The URI must be unique so that it is a one-to-one match – one URI per one data object.
  • Be as human-friendly as possible - URIs should be designed with the end user in mind. SEO and ease of development should come second.
  • Consistency - URIs across a site must be consistent in format. Once you pick your URI structure, be consistent and follow it!
  • “Hackable” URIs - Related to consistency, URIs should be structured so that they are intelligibly “hackable” or changeable.
  • Keywords - The URI should be composed of keywords that are important to the content of the page. So, if the URI is for a blog post that has a long title, only the words important to the content of the page should be in the URI.

When it comes to technical details, here are their concerned bullet-points:

  • No WWW - The www. should be dropped from the website URI, as it is unnecessary typing and violates the rules of being as human-friendly as possible and not including unnecessary information in the URI.
  • Format - Google News has some interesting requirements for webpages that want to be listed in the Google News results – Google requires at least a 3-digit unique number.
  • All lowercase - All characters must be lowercase. Attempting to describe a URI to someone when mixed case is involved is next to impossible.
  • URI identifiers should be made URI friendly - A URI might contain the title of a post, and that title might contain characters that are not URI-friendly. That post title must therefore be made URI friendly. [...] Spaces should be replaced with hyphens.

Scott Mitchell has written an article on 4GuysFromRolla.com about Techniques for Preventing Duplicate URLs in Your Website.

A key tenet of search engine optimization is URL normalization, or URL canonicalization. URL normalization is the process of eliminating duplicate URLs in your website. This article explores four different ways to implement URL normalization in your ASP.NET website.

The important subjects of this article are the following:

  • First Things First: Deciding on a Canonical URL Format - Before we examine techniques for normalizing URLs, and certainly before such techniques can be implemented, we must first decide on a canonical URL format.
  • URL Normalization Using Permanent Redirects - [...] when a search engine spider receives a 301 status it updates its index with the new URL. Therefore, if anytime a request comes in for a non-canonical URL we immediately issue a permanent redirect to the same page but use the canonical form then a search engine spider crawling our site will only maintain the canonical form in its index.
  • Issuing Permanent Redirects From ASP.NET - Every time an incoming request is handled by the ASP.NET engine, it raises the BeginRequest event. You can execute code in response to this event by creating an HTTP Module or by creating the Application_BeginRequest event handler in Global.asax.
  • Rewriting URLs Into Canonical Form Using IIS 7's URL Rewrite Module - Shortly after releasing IIS 7, Microsoft created and released a free URL Rewrite Module. The URL Rewrite Module makes it easy to define URL rewriting rules in your Web.config file.
  • Rewriting URLs Into Canonical Form Using ISAPI_Rewrite - Microsoft's URL Rewriter Module is a great choice if you are using IIS 7, but if you are using previous version of IIS you're out of luck.
  • Telling Search Engine Spiders Your Canonical Form In Markup - Consider a URL that may include querystring parameters that don't affect the content rendered on the page or only affect non-essential parts of the page.
    In the case of YouTube, all video pages specify a <link> element like so, regardless of whether the querystring includes just the videoId or the videoId and other parameters:
    <link rel="canonical" href="/watch?v=videoId">
    

2010-03-31

ASP.NET WebForms SEO: Compressing View State

In my previous post about Moving View State to Bottom of the Form I touched on one way to do some Search Engine Optimization in ASP.NET WebForms. Another thing you can do is to compress large View States on a page.

All the code in this article should be put in a class inheriting from System.Web.UI.Page. Like a page's Code-behind file or your own PageBase-class.

First we need some common logic for both loading and saving a compressed View State, the name of the hidden field to use.

private const string ViewStateFieldName = "SEOVIEWSTATE";

We start with the loading-part, where you see the use of my implementation of the CompressionHelper-class, which simplifies compression. It also solves the issue with DeflateStream and GZipStream inflating already compressed data, which is resolved in .NET Framework 4.

protected override object LoadPageStateFromPersistenceMedium() {
    return LoadCompressedPageState();
}

private object LoadCompressedPageState() {
    string viewState = Request.Form[ViewStateFieldName];
    if(string.IsNullOrEmpty(viewState)) {
        return string.Empty;
    }

    byte[] bytes = Convert.FromBase64String(viewState.Substring(1));

    bool isCompressed = Convert.ToBoolean(Convert.ToInt32(viewState.Substring(0, 1)));
    if(isCompressed) {
        bytes = CompressionHelper.Decompress(bytes);
    }

    string decompressedBase64 = Convert.ToBase64String(bytes);

    ObjectStateFormatter formatter = new ObjectStateFormatter();
    return formatter.Deserialize(decompressedBase64);
}

We then move on to the implementation of saving the page's state.

protected override void SavePageStateToPersistenceMedium(object state) {
    SaveCompressedPageState(state);
}

private void SaveCompressedPageState(object state) {
    byte[] viewStateBytes;
    using(MemoryStream stream = new MemoryStream()) {
        ObjectStateFormatter formatter = new ObjectStateFormatter();
        formatter.Serialize(stream, state);
        viewStateBytes = stream.ToArray();
    }

    byte[] compressed;
    bool successfulCompress = CompressionHelper.TryCompress(viewStateBytes, out compressed);
    string compressedBase64 =
        Convert.ToInt32(successfulCompress) + Convert.ToBase64String(compressed);

    ClientScript.RegisterHiddenField(ViewStateFieldName, compressedBase64);
}

So the summary is that this will compress the View State of an ASP.NET WebForms page, if the View State is large enough. Otherwise it will just keep it the way it is.