[
Advertise | Submit Code | About us | Contact us | Link us
]
Go!
Membership Services
Login
Register

Home
C# General

General

C# Language

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting
C# Windows Forms

General

Combo and List boxes

Miscellaneous Controls

Button Controls

Edit Controls
Cutting Edge

ASP.NET 2.0

Visual Studio 2005

Windows Longhorn

SQL Server 2005
C# Multimedia and GDI+

General

DirectX

GDI+

Audio
Internet & Web

General

Images and multimedia

Database

Utilities

Security

ASP.NET Controls

Design and Architecture

Webservices
.NET

General

Design & Architecture

Algorithms

Database

Security

Active Directory

COM Interop

Remoting

ADO.NET

XML.NET

Tools

Enterprise

IDE
Visual Basic .NET

VB.NET General

VB.NET Controls
General Reading

.NET Books Review

Product Showcase

Book Chapters

Business Design & Strategy
Community

Discuss

Job Board

Discussion

CodeXchange
DeveloperLand

Advertise

Submit Code

About us

Contact us

Link us
Miscellaneous

Favorite Links

Downloads

Programming Sites

Top Stories
Regular Expressions

E-Mail

Date/Time
Home > C# Windows Forms > General
Converting Excel spreadsheets to .rex files with ResxWriter
Posted by on Wednesday, May 11, 2005 (EST)

ResxWriter is a .NET tool that can read Excel spreadsheets with data used for translation, and convert this data into separate .resx files.

This article has been viewed: 4,731 times
Technology: General.

ResxWriter binary (MSI Installer).zip (240.43 KB)
ResxWriter source.zip (1.05 MB)

Contents

Introduction

This is my first article so bear with me :) I want to share this with you because I think ResxWriter has some very nice functionality and some cool features. A break down:

  • Generates .resx files using ADO.NET and an Excel spreadsheet.
  • Fully customizable.
  • Settings are per machine user.
  • Clean uninstallation, with launcher.

ResxWriter is a .NET tool that can read Excel spreadsheets with data used for translation, and convert this data into separate .resx files.

Recently, I was working on an ASP.NET application that needed to have full translation for all static text. We used .NET resource files (.resx) and things were moving along just fine. Updating the text, however, was another story. Using Visual Studio to manually update the .resx files was cumbersome to say the least. Formatting was a pain if you used the IDE, although formatting the XML was an option…

Instead I decided to write an app that would take data from an Excel spreadsheet and generate the .resx files. This allowed our translation staff to use a program they are familiar with, as well as share the files for others to work on.

Top Go to Table of Contents

Reading the Excel File

Suppose you had the following data in a spreadsheet:

ControlName English French
BtnHello Hello World! Bonjour Monde!
LblHello Hello World Again! Bonjour Monde encore!

ResxWriter can extract the data from each column and create .resx files. Any number of columns can be used, and the application can be fully customized.

public bool GetDataFromExcelFile(string filePath)
{
    try
    {
        string strConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" 
        + filePath + @";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""";
        OleDbConnection dbConn = new OleDbConnection(strConnectionString);
        dbConn.Open();
        string fetch = BuildCommand();
        OleDbCommand cmdSelect = new OleDbCommand(fetch, dbConn);
        OleDbDataAdapter dbAdapter = new OleDbDataAdapter();
        dbAdapter.SelectCommand = cmdSelect;
        dbAdapter.Fill(this.m_table);
        dbConn.Close();
        dbConn = null;
        return true;
    }
    catch(System.Data.OleDb.OleDbException ex)
    {
        FrmMessage m = new FrmMessage();
        m.SetMessageText("ResxWriter - Error Message", 
            "Cannot Load Excel File!\n\n\nException:\n\n" 
            + ex.ToString());
        m.ShowDialog();
        return false;
    }
}

Top Go to Table of Contents

Writing the Resource Files

I created a class ClsLanguage to encapsulate the name-value functionality.

[Serializable]
public class ClsLanguage 
{
    private string langColumnName; 
    private string langCulture;
    public ClsLanguage() {} 
    
    public ClsLanguage(string columnName, string culture) 
    { 
        this.langColumnName = columnName; 
        this.langCulture = culture; 
    } 
    [XmlElement(ElementName = "LanguageColumnName")]
    public string LanguageColumnName 
    {
        get {return this.langColumnName;} 
        set {this.langColumnName = value;} 
    } 
    [XmlElement(ElementName = "LanguageCulture")] 
    public string LanguageCulture 
    { 
        get {return this.langCulture;} 
        set {this.langCulture = value;} 
    }
}

A strongly-typed collection of ClsLanguage objects is written out as Resource Files.

public void WriteResources(string filePath)
{
    if (filePath.Length > 0)
    {
        // get columns //
        foreach (ClsLanguage l in ClsMain.settings.LanguageCollection)
        {
            ResXResourceWriter rw = 
              new ResXResourceWriter(filePath + "." + 
              l.LanguageCulture + ".resx");
            for (int i=0; i < this.m_table.Rows.Count; i++)
            {
                ClsMain.frmMain.WriteProgressBar.Visible = true;
                ClsMain.frmMain.WriteProgressBar.Maximum = m_table.Rows.Count;
                try
                {
                    string name = 
                      m_table.Rows[i][ClsMain.settings.ControlColumnName].ToString();
                    string valu = m_table.Rows[i][l.LanguageColumnName].ToString();
                    rw.AddResource(name, valu);
                    ClsMain.frmMain.WriteProgressBar.Increment(i);
                }
                catch (System.ArgumentException)
                {
                }
            }
            rw.Generate();
            rw.Close();
        }
        ClsMain.frmMain.WriteProgressBar.Visible = false;
        FrmMessage m = new FrmMessage();
        m.SetMessageText("ResxWriter - Output Results",
            "Files were written to: " + filePath);
        m.ShowDialog();
    }
}

Top Go to Table of Contents

Points of Interest

Application settings (size, location and column names) were serialized through a class, ClsSettings.

[Serializable]        
public class ClsSettings
{        
    private readonly string m_settingsPath = Application.UserAppDataPath + @"\ResxWriter.xml";
    privateClsLanguageCollection m_langCollection = new ClsLanguageCollection();
    private Size m_size = new Size(250, 175);
    private Point m_location = new Point(200, 200);
    private string m_controlColumnName;
    private string m_sheetName;
    public ClsSettings()
    {
    }
    public string SettingsPath
    {
        get {return this.m_settingsPath;}
    }
    public ClsLanguageCollection LanguageCollection
    {
        get {return this.m_langCollection;}
    }
    public Size FormSize
    {
        get {return this.m_size;}
        set {this.m_size = value;}
    }
    public Point FormLocation
    {
        get {return this.m_location;}
        set {this.m_location = value;}
    }
    public string ControlColumnName
    {
        get {return this.m_controlColumnName;}
        set {this.m_controlColumnName = value;}
    }
    public string SheetName
    {
        get {return this.m_sheetName;}
        set {this.m_sheetName = value;}
    }
}

This allowed me to save (and load) application settings with a few lines of code:

XmlSerializer xs = new XmlSerializer(typeof(ClsSettings));
using (StreamWriter sw = new StreamWriter(xml, false))
{
    ClsMain.settings.FormSize = ClsMain.frmMain.Size;
    ClsMain.settings.FormLocation = ClsMain.frmMain.Location;
    xs.Serialize(sw, ClsMain.settings);
}

All settings in this app are specific to the current user, saved at /Documents and Settings/{User name}/Application Data/... This conforms closely to Microsoft's recommendations, and lets each user have their own experience and preferences.

I hate it when an application uninstalls but doesn't remove all files it was using. So, I made an app that cleans up for a true uninstallation. It essentially deletes all directories and files in its current location. Also, the only method (through Visual Studio) to create an uninstallation icon was to create a Uninstallation Launcher. In the source code, the launcher finds the product key used by the MSI file. This triggers the repair or remove screen, and allows uninstallation.

(These are both included as separate projects in the Solution file.)

--------------------------------------------------------------------

Article By: Patrick Bounaix

Article Website:
http://resxwriter.l0g1c4l.com

Top Go to Table of Contents

About Patrick Bounaix

Click here if you want to know more about .

Other articles that may interest you

  • Write a Word Add-In – Part 0
  • Write a Word Add-In – Part I
  • Lengthy Operations on Single Thread in .NET Application
  • Learning Draughts
  • Exceptions and Performance
  • Average Rating :

    Discussion Forums
    Got a programming related question? Hopefully someone has the answer... Want to help out other developers? Visit our discussion forums.

    Sponsored by:

    New Articles

  • Exceptions and Performance
    Almost every time exceptions are mentioned in mailing lists and newsgroups, people say they're really expensive.Let's examine that claim, shall we?

  • Creating multilingual websites - Part 1
    Extend the existing globalization capabilities of .NET to create flexible and powerful multilingual web sites. First, create a custom ResourceManager, and then create custom localized-capable server controls to easily deploy multilingual functionality.

  • Parameter passing in C#
    Many people have become fairly confused about how parameters are passed in C#, particularly with regard to reference types. This page should help to clear up some of that confusion

  • Most Popular Articles

  • LDAP, IIS and WinNT Directory Services
    This article explains how to use .NET Directory Services to retrieve and search directory objects, create new directory objects and edit or delete existing directory objects. Describes Active Directory Application Mode (ADAM) and how to use the IIS, WinNT and LDAP directory (ADSI) provider.

  • An in-depth look at WMI and instrumentation, Part II
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article is the second part of a two-part series.

  • An in-depth look at WMI and instrumentation, Part I
    WMI stands for Windows Management Instrumentation and, as the name indicates, is about managing your IT infrastructure this article provides an in-depth look at WMI and MOM 2005

  • New Books

  • Murach's ASP.NET 2.0 Upgrader's Guide: VB Edition
    What’s new and how to use it! That’s what this book delivers if you’re a VB developer who’s interested in upgrading from ASP.NET 1.x to ASP.NET 2.0.

  • C# in easy steps
    Learn to program with Microsoft’s premier programming language. No previous programming knowledge is assumed. With numerous easy-to-follow examples, this title explains the essentials of object-oriented programming with C#.

  • Murach's ASP.NET web programming with VB.NET
    Murach's ASP.NET web programming with VB.NET by Doug Lowe and Anne Prince is a in depth training and reference book for ASP.NET programming using VB.NET. The book builds upon Murach's previous books and covers more advanced concepts for programming ASP.NET pages.

  • Got Code?

    if you have any article , source code , or anything else you'd like to share with this community that you think others might find useful, please submit it here and we will gladly make it available on this site. submit@developerland.com.
    Partners

    All articles are copyrighted by their individual authors unless otherwise specified , everything else Copyright ©2004-2006 DeveloperLand