Introduction
When I was guiding my team for a specific project for one of my clients, I foresaw that part of my project was leading towards document management system. The client wants the documents to be viewed, it includes pdf/word/txt/scanned image of many formats, etc. But for all means, they faced the problem of opening individual applications and also the licensing cost. Also, it is cumbersome to open and maintain. They requested one solution, which led me to create a tree view approach and document view. When I was initiating this, I was Googling any idea, and most of the time, people drove me towards different directions. But still my problem was not resolved. Even in many forums, people were crying to get a solution for the same.
Once I created this, I want to share with all of you and I hope that it will help you a lot.
Here we are going to achieve two things in this article:
- Display the files of a specific folder in the
TreeView
- Display the content of the files in the same aspx page right pane using iframe
Components we are going to use are Interops of Word and Excel.
First from Visual Studio, create a new web application solution.
Right click the solution and add a new project, select Project Type as Class Library.
Name the Class Library Project as “LibraryConvertor
”. Now rename the Class1.cs to “WordXLS
”. In the add reference of the Class Library, add the following interops, Interop.Word.dll and Interop.Excel.dll.
Let us create the data members in this class library WordXLS.cs as follows:
#region Data Members
public string Message = string.Empty;
private Word.ApplicationClass OfficeWord;
private Excel.ApplicationClass OfficeExcel;
object Unknown = Type.Missing;
public enum StatusType { SUCCESS, FAILED };
public StatusType Status;
#endregion
In the default constructor, the Status
and Message
we shall initialize are as follows:
public WordExcelToHTML()
{
Status = StatusType.FAILED;
Message = string.Empty;
}
We shall create a method which converts the Word Document to HTML and the signature as follows:
public void WordToHTML(object Source, object Target)
Here Source
and Target
are the filenames. As the Word Active Document always accepts object, here we are also accepting as objects. When we open the document, the application window shouldn’t open explicitly. To suppress, the following code helps us:
OfficeWord.Visible = false;
OfficeWord.Application.Visible = false;
OfficeWord.WindowState = Word.WdWindowState.wdWindowStateMinimize;
For opening the specific document, the Open
method of the ApplicationClass
object is used as follows:
OfficeWord.Documents.Open(ref Source, ref Unknown,
ref Unknown, ref Unknown, ref Unknown,
ref Unknown, ref Unknown, ref Unknown,
ref Unknown, ref Unknown, ref Unknown,
ref Unknown, ref Unknown, ref Unknown, ref Unknown);
Note, here we are passing only the Source
and remaining arguments as empty. Following are the arguments and its purpose of the Open
method.
SlNo | Argument Type |
1 | FileName |
2 | ConfirmConversions |
3 | ReadOnly |
4 | AddToRecentFiles |
5 | PasswordDocument |
6 | PasswordTemplate |
7 | Revert |
8 | WritePasswordDocument |
9 | WritePasswordTemplate |
10 | Format |
11 | Encoding |
12 | Visible |
13 | OpenAndRepair |
14 | DocumentDirection |
15 | NoEncodingDialog |
object format = Word.WdSaveFormat.wdFormatHTML;
Here we are specifying to convert to HTML format. The List of formats to which can be converted are as follows:
SlNo | Argument Type |
1 | wdFormatDocument |
2 | wdFormatDOSText |
3 | wdFormatDOSTextLineBreaks |
4 | wdFormatEncodedText |
5 | wdFormatFilteredHTML |
6 | wdFormatHTML |
7 | wdFormatRTF |
8 | wdFormatTemplate |
9 | wdFormatText |
10 | wdFormatTextLineBreaks |
11 | wdFormatUnicodeText |
12 | wdFormatWebArchive |
You can explore the above two tables respectively. Here anyway we try to convert to HTML.
Open
and FormatHTML
should be inside the try
...catch
block. Thus any exceptions can be caught respectively.
Now it is time for us to save as HTML using the Target
file name as follows.
OfficeWord.ActiveDocument.SaveAs(ref Target, ref format,
ref Unknown, ref Unknown, ref Unknown,
ref Unknown, ref Unknown, ref Unknown,
ref Unknown, ref Unknown, ref Unknown,
ref Unknown, ref Unknown, ref Unknown,
ref Unknown, ref Unknown);
Status = StatusType.SUCCESS;
Message = Status.ToString();
Following are the different arguments for you to explore further:
SlNo | Argument Type |
1 | FileName |
2 | FileFormat |
3 | LockComments |
4 | Password |
5 | AddToRecentFiles |
6 | WritePassword |
7 | ReadOnlyRecommended |
8 | EmbedTrueTypeFonts |
9 | SaveNativePictureFormat |
10 | SaveFormsData |
11 | SaveAsAOCELetter |
12 | Encoding |
13 | InsertLineBreaks |
14 | AllowSubstitutions |
15 | LineEnd<code> ing |
In the finally
block, let us dispose the objects we have instantiated.
finally
{
if (OfficeWord != null)
{
OfficeWord.Documents.Close(ref Unknown, ref Unknown, ref Unknown);
OfficeWord.Quit(ref Unknown, ref Unknown, ref Unknown);
}
}
For Excel Operations, the following method needs to be created:
public void ExcelToHTML(string Source, string Target)
In this, we shall take Source
and Target
as it is as string
because the Excel class accepts as String
only.
Similarly for Open
and SaveAs
, let us follow as it is in Word, but note, the parameters have differences. I leave it for you to explore further. You will enjoy more when you do this for different formats.
Please refer to the code in the attached sample.
Now the Class Library is completed. We have to create a web form for this library to consume.
Add our “LibraryConvertor
” assembly to the reference of our web application.
First delete your Default.aspx and create a new form and name it as “LandingPage.aspx”.
The Markup should look like the following:
In our aspx file, we have to do the following.
Add the scriptManager
:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
Add a table with two columns, left for TreeView
and Right for iframe
.
The code should look like the following:
In the DesignMode
, select the TreeView
and two Events
properties, double click the selected Node changed event “DocView_TreeView_SelectedNodeChanged
” and move to the code behind.
In our Code Behind, include the Library’s namespace as follows:
using LibraryConvertor;
and instantiate the WordXLS
class.
Add the following two keys in the appsettings
of the web.config:
<add key="ConvertLocation" value="D:\ TreeView_DocView\target\"/>
<add key="ErrorFile" value="D:\ TreeView_DocView\target\ErrorPage.jpg"/>
Correspondingly, create a folder called target in our application folder. Also add an Error Jpeg also in the same directory.
Include this namespace:
using System.IO;
Create a method as follows in order to retrieve the files from the specific folder which are to be provided to the tree view:
TreeNode OutputDirectory(System.IO.DirectoryInfo directory, TreeNode parentNode)
{
if (directory == null) return null;
TreeNode DirNode = new TreeNode(directory.Name);
System.IO.FileInfo[] Files = directory.GetFiles();
for (int FileCount = 0; FileCount < Files.Length; FileCount++)
DirNode.ChildNodes.Add(new TreeNode(Files[FileCount].Name));
if (parentNode == null)
return DirNode;
else
{
parentNode.ChildNodes.Add(DirNode);
return parentNode;
}
}
Also create one more method which actually does Tree Clear functionality and calls the OutputDirectory
method actually.
private void BindTree()
{
DocViewTreeView.Nodes.Clear();
DirectoryInfo RootDir = new DirectoryInfo(Server.MapPath("~/target"));
TreeNode RootNode = OutputDirectory(RootDir, null);
DocViewTreeView.Nodes.Add(RootNode);
DocViewTreeView.ExpandAll();
}
From the Page Load Event, as follows:
if (!IsPostBack)
{
lblText.Text = "FileName :Error.jpg";
BindTree();
}
In order to display the ErrorPage.jpg, we have to write the following code in the “DocView_TreeView_SelectedNodeChanged
” event.
WordXLS conv = new WordXLS();
lblText.Text = "FileName :" + DocViewTreeView.SelectedNode.Text;
string strFilePath = ConfigurationManager.AppSettings
["ConvertLocation"].ToString().Trim();
string strFile = DocViewTreeView.SelectedNode.Text.ToString();
string strExtension = DocViewTreeView.SelectedNode.Text.ToString().Split
('.')[1].ToString().Trim().ToUpper();
string strUrl = "http://" + Request.Url.Authority + "/target/";
if (strExtension == "DOCX" || strExtension == "DOC")
{
conv.WordToHTML(strFilePath + strFile, strFilePath + strFile.Split('.')[0] + ".html");
if (conv.Status == WordXLS.StatusType.SUCCESS)
docPreview.Attributes["src"] = strUrl + strFile.Split('.')[0] + ".html";
}
else if (strExtension == "XLS" || strExtension == "XLSX")
{
conv.ExcelToHTML(strFilePath + strFile, strFilePath + strFile.Split('.')[0] + ".html");
if (conv.Status == WordXLS.StatusType.SUCCESS)
docPreview.Attributes["src"] = strUrl + strFile.Split('.')[0] + ".html";
}
else
docPreview.Attributes["src"] = strUrl + DocViewTreeView.SelectedNode.Text;
The “DocViewTreeView.SelectedNode.Text;
” will provide the selected file and the extension of the file must be checked first. Based on the extension, we can call the appropriate “WordToHTML
” or ExcelToHTML
” and fetch the output file, which can then be associated to the “src
” of the docPreview
’s attribute.
Now when we execute, the output should be like the following:
Add a pdf file, a .doc file, .docx, .xls, .xlsx, .txt in the target folder and see, what happens.
For example, find the following excel in the target folder.
Now the output in the browser should look like the following:
Note, the client system need not to have Microsoft Office installed, but they can view all Word and XLS documents in this fashion.
If it is PDF, the client system must have Adobe reader. But definitely now you can do work around for the same.
If it is a text file or any image file, it will display in the iframe
itself.
Points of Interest
Also if it is Excel, one amazing functionality is the sheets will be displayed as a separate toolbar below. By clicking the specific sheet, we can view respective sheets.
Try to delete the HTML file and the _files folder of the respective word/excel file before creation. Otherwise, we get, overwrite yes/no issue.
Don’t forget to explore through all different formats of conversions.
Observations
-
strUrl = "http://" + Request.Url.Authority + "/target/";
-
strExtension == "XLS" || strExtension == "XLSX"
-
strFile.Split('.')[0] + ".html"
I have made it intentionally. Kindly change according to your need. I have used for easy coding in order to make you to understand the exact meaning of what I want to communicate.
History
I will work on improving this application more to make it as a separate document management system as a component.
Author
A. Rishi Ganesh, Project Manager, India
If you have any comments or suggestions, please reach me at rishwins@hotmail.com.