I created a program which collects all the word files from a folder which belongs to our SharePoint library of documents. The program will only grab the documents if they were submitted/are a part of the HR team.
These documents are saved in a temporary folder, and then merged together into one large pdf.
I thought this seemed a bit superfluous, and figured there must be a way of achieving this without having to save the individual pdf files first. Ideally I would also like a way of dynamically creating a table of contents based on the files which are already present.
The files need to be in the correct order, so each document on SharePoint has been assigned an order number.
This list is retrieved so that I have something to order the documents against (as saving them in the file results in them being in their default, alphabetical order, appending the order number to the beginning of the file name also doesn't work, as this orders them as 1, 10, 11, 12 .. etc). I also feel that this can be improved upon. If I can work out how to convert the word files into PDFs without having to save them first, I could sort the FileInfo data before converting.
Does anyone have any ideas or suggestions on how I can improve/implement the above, or any other comments? Any advice/guidance at all is much appreciated.
Program
using System.Collections.Generic;
using System.IO;
namespace PdfConverter
{
class Program
{
#region fields
public static List<string> orderedList;
#endregion fields
static void Main(string[] args)
{
// Get the word files FileInfo
FileInfo[] wordFileInfo = DataGrabber.GetWordFileInfo();
// Instantiate a new 'Convert' object and convert our files to pdf, saving them in a temporary folder
Converter convert = new Converter();
convert.ToPdf(wordFileInfo);
// Get the pdf filenames
var newPdfFiles = DataGrabber.GetPdfFileNames();
convert.MergePdfs(newPdfFiles);
// Delete the files
foreach (var item in orderedList)
{
var newFileName = "\\\\file\\IT\\SK\\test\\" + item.Split('.')[0] + ".pdf";
System.IO.File.Delete(newFileName);
}
}
}
}
DataGrabber
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.SharePoint.Client;
namespace PdfConverter
{
class DataGrabber
{
#region fields
public static string spSite = "http://SharepointSite/WorkingHere";
public static string policyList = "Policies & Procedures";
public static string sortBy = "Sort_x0020_Order";
public static string sourceFolder = @"\\SharepointSite\WorkingHere\PoliciesandProcedures"; \\ network SP folder
#endregion fields
public ListItemCollection GetSpList(string siteName, string listName, string sortBy)
{
// Set the context (URL) of the site ...
ClientContext cc = new ClientContext(siteName);
Web web = cc.Web;
// Get the list by title
Microsoft.SharePoint.Client.List list = web.Lists.GetByTitle(listName);
// A query to fileter the results
CamlQuery caml = new CamlQuery();
caml.ViewXml = "<View>" +
"<Query>" +
"<OrderBy>" +
"<FieldRef Name='" + sortBy + "' Ascending='True'/>" +
"</OrderBy>" +
"</Query>" +
//"<RowLimit>" + strCount + "</RowLimit>" +
"</View>";
// Store the items in a ListItemCollection
ListItemCollection items = list.GetItems(caml);
// Load the client context and execute
cc.Load<Microsoft.SharePoint.Client.List>(list);
cc.Load<ListItemCollection>(items);
cc.ExecuteQuery();
return items;
}
public static FileInfo[] GetWordFileInfo()
{
// Create a new data grabber
DataGrabber d = new DataGrabber();
// Get the SP list using spList - policyList - sortBy
ListItemCollection spList = d.GetSpList(spSite, policyList, sortBy);
// Get a list of the document titles from spList
List<string> hrDocTitles = d.Sort(spList);
// Get the fileinfo from these documents
FileInfo[] wordFiles = d.GetFiles(hrDocTitles);
return wordFiles;
}
public FileInfo[] GetFiles(List<string> fileNames)
{
// Get the fileinfo from each document we added to the docList
var length = fileNames.Count;
string uriPath = sourceFolder;
FileInfo[] wordFiles = new FileInfo[length];
for (int j = 0; j < length; j++)
{
string path = uriPath + "\\" + fileNames[j];
string localPath = new Uri(path).LocalPath;
FileInfo fileInfo = new FileInfo(localPath);
wordFiles[j] = fileInfo;
}
return wordFiles;
}
public List<string> Sort(ListItemCollection spList)
{
List<string> docList = new List<string>();
// For each item in the SPList, check if it is HR and then add it to our lists
foreach (ListItem litem in spList)
{
try
{
var rawTeam = litem.FieldValues["BRTeamHTField0"].ToString();
var team = rawTeam.Substring(0, 2);
var asd = litem.FieldValues["FileLeafRef"];
string title = "";
if (team == "HR" & litem.FieldValues["FileLeafRef"].ToString().Contains(".doc"))
{
try
{
title = litem.FieldValues["FileLeafRef"].ToString();
}
catch (Exception)
{
title = "";
}
docList.Add(title);
}
else
{
// Nothing
}
}
catch
{
}
}
// Update the ordered list field in the main program - used to maintain the correct document order
Program.orderedList = docList;
return docList;
}
public static string[] GetPdfFileNames()
{
// Get list of word files in specified directory
string localPath = new Uri(sourceFolder).LocalPath;
DirectoryInfo dirInfo = new DirectoryInfo(localPath);
FileInfo[] pdfFiles = dirInfo.GetFiles("*.pdf");
var length = pdfFiles.Length; // To exclude the existing HR Policies and Procedures Guide
string[] pdfFileNames = new string[length];
for (int i = 0; i < length; i++)
{
pdfFileNames[i] = localPath + "\\" + pdfFiles[i].Name;
}
Array.Sort(pdfFileNames);
return pdfFileNames;
}
}
}
Converter
using iTextSharp.text;
using iTextSharp.text.pdf;
using Microsoft.Office.Interop.Word;
using System;
using System.IO;
namespace PdfConverter
{
class Converter
{
#region fields
public static string tempTargetFolder = @"\\file\IT\SK\test\";
public static string targetPdf = @"\\file\IT\SK\test\Guide\testOutput.pdf";
#endregion fields
public void ToPdf(FileInfo[] wordFiles)
{
// Takes a FileInfo[] variable and convers each file in it to pdf, saving it to a temporary target folder tempTargetFolder
// Create a new microsoft word application object
Application word = new Application();
word.Visible = false;
word.ScreenUpdating = false;
// I think this can actually be done away with and all oMissing parameters removed, as C# can handle optional parameters ...
object oMissing = System.Reflection.Missing.Value;
// for adding the file name to the temporary pdf files
int counter = 1;
foreach (FileInfo wordFile in wordFiles)
{
// Cast as object for word open method
Object fileName = (Object)wordFile.FullName;
// Use the dummy value as a placeholder for optional arguments
Microsoft.Office.Interop.Word.Document doc = word.Documents.Open(ref fileName, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing);
doc.Activate();
object outputFileName = new object();
if (wordFile.FullName.Contains(".docx"))
{
outputFileName = tempTargetFolder + wordFile.FullName.Split('\\')[5];
outputFileName = outputFileName.ToString().Replace(".docx", ".pdf");
}
else if (wordFile.FullName.Contains(".doc"))
{
outputFileName = tempTargetFolder + wordFile.FullName.Split('\\')[5];
outputFileName = outputFileName.ToString().Replace(".doc", ".pdf");
}
else
{
break;
}
object fileFormat = WdSaveFormat.wdFormatPDF;
// Save document into pdf format
doc.SaveAs(ref outputFileName,
ref fileFormat, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing);
// Close the word document, but leave the word application open.
// Doc has to be cast to type _Document so that it will find the
// correct close method.
object saveChanges = WdSaveOptions.wdDoNotSaveChanges;
((_Document)doc).Close(ref saveChanges, ref oMissing, ref oMissing);
doc = null;
counter++;
}
// word has to be cast to type _Application so that it will find the correct Quit method
((_Application)word).Quit(ref oMissing, ref oMissing, ref oMissing);
word = null;
}
public void MergePdfs(string[] newPdfFiles)
{
using (FileStream stream = new FileStream(targetPdf, FileMode.Create))
{
iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document(PageSize.A4);
PdfCopy pdf = new PdfCopy(pdfDoc, stream);
pdfDoc.Open();
foreach (string file in Program.orderedList)
{
var newFileName = "\\\\file\\IT\\SK\\test\\" + file.Split('.')[0] + ".pdf";
PdfReader test = new PdfReader(newFileName);
pdf.AddDocument(test);
test.Dispose();
}
// pdfDoc.Close(); // Doesn't seem to do anything
pdf.Close();
}
}
}
}