├── Doc ├── Images │ ├── ScipBe.png │ ├── ScipBe.Common.Office.png │ ├── ScipBe.Common.Office.Excel.png │ ├── ScipBe.Common.Office.OneNote.png │ └── ScipBe.Common.Office.Outlook.png ├── LinqPad │ ├── Persons.xls │ ├── Persons.xlsx │ ├── ScipBe.Common.Office.Outlook - Folders.linq │ ├── ScipBe.Common.Office.Outlook - Mails - Statistics.linq │ ├── ScipBe.Common.Office.Outlook - Mails - Move or Delete.linq │ ├── ScipBe.Common.Office.Outlook - Appointments.linq │ ├── ScipBe.Common.Office.Excel - Persons.linq │ ├── ScipBe.Common.Office.Outlook - Contacts.linq │ ├── ScipBe.Common.Office.Outlook - Mails - Delete attachments.linq │ └── ScipBe.Common.Office.OneNote.linq └── Diagrams │ ├── ExcelProvider.png │ ├── OneNoteProvider.png │ └── OutlookProvider.png ├── Src ├── ScipBe.Common.Office.Tests │ ├── Excel │ │ ├── Persons.xls │ │ ├── Persons.xlsx │ │ └── ExcelProvidertTest.cs │ ├── ScipBe.Common.Office.Tests.csproj │ ├── OneNote │ │ └── OneNoteProviderTest.cs │ └── Outlook │ │ └── OutlookProvidertTest.cs ├── ScipBe.Common.Office │ ├── Images │ │ └── ScipBe.Common.Office.png │ ├── OneNote │ │ ├── OneNoteExtSection.cs │ │ ├── OneNoteExtNotebook.cs │ │ ├── OneNoteExtPage.cs │ │ ├── OneNoteSection.cs │ │ ├── OneNoteNotebook.cs │ │ ├── IOneNoteExtSection.cs │ │ ├── IOneNoteExtNotebook.cs │ │ ├── IOneNoteExtPage.cs │ │ ├── IOneNoteNotebook.cs │ │ ├── IOneNoteSection.cs │ │ ├── OneNotePage.cs │ │ ├── IOneNoteProvider.cs │ │ ├── IOneNotePage.cs │ │ └── OneNoteProvider.cs │ ├── Excel │ │ ├── FileType.cs │ │ ├── IExcelColumn.cs │ │ ├── ExcelColumn.cs │ │ ├── IExcelProvider.cs │ │ ├── IExcelRow.cs │ │ ├── ExcelRow.cs │ │ └── ExcelProvider.cs │ ├── Utils │ │ ├── StringExtensions.cs │ │ └── Util.cs │ ├── Outlook │ │ ├── OlItemTypeExtensions.cs │ │ ├── ContactItemExtensions.cs │ │ ├── IOutlookProvider.cs │ │ └── OutlookProvider.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── ScipBe.Common.Office.csproj │ ├── ScipBe.Common.Office.nuspec │ └── Class diagrams │ │ ├── ExcelProvider.cd │ │ ├── OutlookProvider.cd │ │ └── OneNoteProvider.cd ├── ScipBe.Common.Office.Excel │ ├── Images │ │ └── ScipBe.Common.Office.Excel.png │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── ScipBe.Common.Office.Excel.nuspec │ └── ScipBe.Common.Office.Excel.csproj ├── ScipBe.Common.Office.OneNote │ ├── Images │ │ └── ScipBe.Common.Office.OneNote.png │ ├── ScipBe.Common.Office.OneNote.nuspec │ ├── Properties │ │ └── AssemblyInfo.cs │ └── ScipBe.Common.Office.OneNote.csproj ├── ScipBe.Common.Office.Outlook │ ├── Images │ │ └── ScipBe.Common.Office.Outlook.png │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── ScipBe.Common.Office.Outlook.csproj │ └── ScipBe.Common.Office.Outlook.nuspec └── ScipBe.Common.Office.sln ├── LICENSE ├── README.md └── .gitignore /Doc/Images/ScipBe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/Images/ScipBe.png -------------------------------------------------------------------------------- /Doc/LinqPad/Persons.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/LinqPad/Persons.xls -------------------------------------------------------------------------------- /Doc/LinqPad/Persons.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/LinqPad/Persons.xlsx -------------------------------------------------------------------------------- /Doc/Diagrams/ExcelProvider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/Diagrams/ExcelProvider.png -------------------------------------------------------------------------------- /Doc/Diagrams/OneNoteProvider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/Diagrams/OneNoteProvider.png -------------------------------------------------------------------------------- /Doc/Diagrams/OutlookProvider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/Diagrams/OutlookProvider.png -------------------------------------------------------------------------------- /Doc/Images/ScipBe.Common.Office.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/Images/ScipBe.Common.Office.png -------------------------------------------------------------------------------- /Doc/Images/ScipBe.Common.Office.Excel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/Images/ScipBe.Common.Office.Excel.png -------------------------------------------------------------------------------- /Doc/Images/ScipBe.Common.Office.OneNote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/Images/ScipBe.Common.Office.OneNote.png -------------------------------------------------------------------------------- /Doc/Images/ScipBe.Common.Office.Outlook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Doc/Images/ScipBe.Common.Office.Outlook.png -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Tests/Excel/Persons.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Src/ScipBe.Common.Office.Tests/Excel/Persons.xls -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Tests/Excel/Persons.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Src/ScipBe.Common.Office.Tests/Excel/Persons.xlsx -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Images/ScipBe.Common.Office.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Src/ScipBe.Common.Office/Images/ScipBe.Common.Office.png -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Excel/Images/ScipBe.Common.Office.Excel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Src/ScipBe.Common.Office.Excel/Images/ScipBe.Common.Office.Excel.png -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.OneNote/Images/ScipBe.Common.Office.OneNote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Src/ScipBe.Common.Office.OneNote/Images/ScipBe.Common.Office.OneNote.png -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Outlook/Images/ScipBe.Common.Office.Outlook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scipbe/ScipBe-Common-Office/HEAD/Src/ScipBe.Common.Office.Outlook/Images/ScipBe.Common.Office.Outlook.png -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/OneNoteExtSection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace ScipBe.Common.Office.OneNote 5 | { 6 | internal class OneNoteExtSection : OneNoteSection, IOneNoteExtSection 7 | { 8 | public IEnumerable Pages { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/OneNoteExtNotebook.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace ScipBe.Common.Office.OneNote 5 | { 6 | internal class OneNoteExtNotebook : OneNoteNotebook, IOneNoteExtNotebook 7 | { 8 | public IEnumerable Sections { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/OneNoteExtPage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Office.Interop.OneNote; 2 | 3 | namespace ScipBe.Common.Office.OneNote 4 | { 5 | internal class OneNoteExtPage : OneNotePage, IOneNoteExtPage 6 | { 7 | public OneNoteExtPage() 8 | : base() { } 9 | 10 | public IOneNoteSection Section { get; set; } 11 | public IOneNoteNotebook Notebook { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/OneNoteSection.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace ScipBe.Common.Office.OneNote 4 | { 5 | internal class OneNoteSection : IOneNoteSection 6 | { 7 | public string ID { get; set; } 8 | public string Name { get; set; } 9 | public string Path { get; set; } 10 | public bool Encrypted { get; set; } 11 | public Color? Color { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/OneNoteNotebook.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace ScipBe.Common.Office.OneNote 4 | { 5 | internal class OneNoteNotebook : IOneNoteNotebook 6 | { 7 | public string ID { get; set; } 8 | public string Name { get; set; } 9 | public string NickName { get; set; } 10 | public string Path { get; set; } 11 | public Color? Color { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/IOneNoteExtSection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ScipBe.Common.Office.OneNote 4 | { 5 | /// 6 | /// Section in OneNote with collection of Pages. 7 | /// 8 | public interface IOneNoteExtSection : IOneNoteSection 9 | { 10 | /// 11 | /// Collection of pages. 12 | /// 13 | IEnumerable Pages { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/IOneNoteExtNotebook.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ScipBe.Common.Office.OneNote 4 | { 5 | /// 6 | /// Notebook in OneNote with collection of Sections. 7 | /// 8 | public interface IOneNoteExtNotebook : IOneNoteNotebook 9 | { 10 | /// 11 | /// Collection of sections. 12 | /// 13 | IEnumerable Sections { get; } 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/IOneNoteExtPage.cs: -------------------------------------------------------------------------------- 1 | namespace ScipBe.Common.Office.OneNote 2 | { 3 | 4 | /// 5 | /// Page with reference to Section and Notebook. 6 | /// 7 | public interface IOneNoteExtPage : IOneNotePage 8 | { 9 | /// 10 | /// Section of Page. 11 | /// 12 | IOneNoteSection Section { get; } 13 | /// 14 | /// Notebook of Page. 15 | /// 16 | IOneNoteNotebook Notebook { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /Doc/LinqPad/ScipBe.Common.Office.Outlook - Folders.linq: -------------------------------------------------------------------------------- 1 | 2 | ScipBe.Common.Office.Outlook 3 | Microsoft.Office.Interop.Outlook 4 | ScipBe.Common.Office.Outlook 5 | 6 | 7 | void Main() 8 | { 9 | Util.RawHtml($"

ScipBe.Common.Office.Outlook - LINQ to Outlook - Query folders

").Dump(); 10 | 11 | var outlookProvider = new OutlookProvider(); 12 | 13 | outlookProvider.Folders.Select(f => 14 | new 15 | { 16 | f.FolderPath, 17 | f.Name, 18 | f.DefaultItemType, 19 | f.UnReadItemCount, 20 | SubfoldersCount = f.Folders.Count, 21 | ItemsCount = f.Items.Count, 22 | }).Dump("All Outlook folders"); 23 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Excel/FileType.cs: -------------------------------------------------------------------------------- 1 | namespace ScipBe.Common.Office.Excel 2 | { 3 | /// 4 | /// File type. 5 | /// 6 | /// 7 | /// Connection strings 8 | /// 9 | /// XLSX: @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=FileName;Extended Properties=""Excel 12.0 Xml;HDR=YES""" 10 | /// XLS: @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=FileName;Extended Properties=""Excel 8.0;HDR=YES""" 11 | /// 12 | /// 13 | public enum FileType 14 | { 15 | /// 16 | /// Excel 97-2003 (v8-v11). 17 | /// 18 | Xls, 19 | /// 20 | /// Excel 2007-2019 (v12-v16). 21 | /// 22 | Xlsx 23 | }; 24 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Excel/IExcelColumn.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ScipBe.Common.Office.Excel 4 | { 5 | /// 6 | /// Interface for column definition of Excel worksheet. 7 | /// 8 | public interface IExcelColumn 9 | { 10 | /// 11 | /// Column index, 1 - 999999. 12 | /// 13 | int Index { get; } 14 | 15 | /// 16 | /// Column header, A - Z, AA - ZZ, ... 17 | /// 18 | string Header { get; } 19 | 20 | /// 21 | /// Column name. String name in first row of Excel worksheet. 22 | /// 23 | string Name { get; } 24 | 25 | /// 26 | /// Column type (string, int, datetime, ...). 27 | /// 28 | Type Type { get; } 29 | } 30 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/IOneNoteNotebook.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace ScipBe.Common.Office.OneNote 4 | { 5 | /// 6 | /// Notebook in OneNote. 7 | /// 8 | public interface IOneNoteNotebook 9 | { 10 | /// 11 | /// ID of Notebook. 12 | /// 13 | string ID { get; } 14 | /// 15 | /// Name of Notebook. 16 | /// 17 | string Name { get; } 18 | /// 19 | /// Nickname of Notebook. 20 | /// 21 | string NickName { get; } 22 | /// 23 | /// Physical file path of Notebook. 24 | /// 25 | string Path { get; } 26 | /// 27 | /// Color of tab of Notebook. 28 | /// 29 | Color? Color { get; } 30 | } 31 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/IOneNoteSection.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace ScipBe.Common.Office.OneNote 4 | { 5 | /// 6 | /// Section in OneNote. 7 | /// 8 | public interface IOneNoteSection 9 | { 10 | /// 11 | /// ID of Section. 12 | /// 13 | string ID { get; } 14 | 15 | /// 16 | /// Name of Section. 17 | /// 18 | string Name { get; } 19 | 20 | /// 21 | /// Physical file path of Section. 22 | /// 23 | string Path { get; } 24 | 25 | /// 26 | /// Is Section encrypted? 27 | /// 28 | bool Encrypted { get; } 29 | 30 | /// 31 | /// Color of tab of section. 32 | /// 33 | Color? Color { get; } 34 | } 35 | } -------------------------------------------------------------------------------- /Doc/LinqPad/ScipBe.Common.Office.Outlook - Mails - Statistics.linq: -------------------------------------------------------------------------------- 1 | 2 | ScipBe.Common.Office.Outlook 3 | Microsoft.Office.Interop.Outlook 4 | ScipBe.Common.Office.Outlook 5 | 6 | 7 | void Main() 8 | { 9 | Util.RawHtml($"

ScipBe.Common.Office.Outlook - LINQ to Outlook - Statistics about mails

").Dump(); 10 | 11 | var outlookProvider = new OutlookProvider(); 12 | 13 | var mails = outlookProvider.InboxItems; 14 | //var mails = outlookProvider.SentMailItems; 15 | //var mails = outlookProvider.GetItems(@"\\account\Mailbox OUT"); 16 | 17 | var query = 18 | from m in mails 19 | orderby m.SentOn descending 20 | group m by $"{m.SentOn.Date.Year}-{m.SentOn.Date.Month}" into g 21 | select new 22 | { 23 | SentOn = g.Key, 24 | Count = g.Count() 25 | }; 26 | 27 | query.Dump("Mail statistics"); 28 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Excel/ExcelColumn.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ScipBe.Common.Office.Excel 4 | { 5 | internal class ExcelColumn : IExcelColumn 6 | { 7 | public ExcelColumn(int index, string name, Type type) 8 | { 9 | Index = index + 1; 10 | Name = name; 11 | Type = type; 12 | Header = CalcHeader(index + 1); 13 | } 14 | 15 | private static string CalcHeader(int index) 16 | { 17 | int number = index; 18 | string headerText = ""; 19 | while (number > 0) 20 | { 21 | headerText = (Char)(((number - 1) % 26) + 65) + headerText; 22 | number = (number - 1) / 26; 23 | } 24 | return headerText; 25 | } 26 | 27 | public int Index { get; set; } 28 | public string Header { get; set; } 29 | public string Name { get; set; } 30 | public Type Type { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/OneNotePage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Office.Interop.OneNote; 3 | 4 | namespace ScipBe.Common.Office.OneNote 5 | { 6 | internal class OneNotePage : IOneNotePage 7 | { 8 | public OneNotePage() 9 | { 10 | } 11 | 12 | public string ID { get; set; } 13 | public string Name { get; set; } 14 | public int Level { get; set; } 15 | public DateTime DateTime { get; set; } 16 | public DateTime LastModified { get; set; } 17 | 18 | public string GetContent() 19 | { 20 | return OneNoteProvider.CallOneNoteSafely(oneNote => 21 | { 22 | oneNote.GetPageContent(this.ID, out string content); 23 | return content; 24 | }); 25 | } 26 | 27 | public void OpenInOneNote() 28 | { 29 | OneNoteProvider.CallOneNoteSafely(oneNote => 30 | { 31 | oneNote.NavigateTo(this.ID); 32 | return true; 33 | }); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Doc/LinqPad/ScipBe.Common.Office.Outlook - Mails - Move or Delete.linq: -------------------------------------------------------------------------------- 1 | 2 | ScipBe.Common.Office.Outlook 3 | Microsoft.Office.Interop.Outlook 4 | ScipBe.Common.Office.Outlook 5 | 6 | 7 | void Main() 8 | { 9 | Util.RawHtml($"

ScipBe.Common.Office.Outlook - LINQ to Outlook - Move or Delete Mails

").Dump(); 10 | 11 | var outlookProvider = new OutlookProvider(); 12 | 13 | var mailItems = outlookProvider.InboxItems; 14 | //var mailItems = outlookProvider.SentMailItems; 15 | //var mailItems = outlookProvider.GetItems(@"\\account\Mailbox IN"); 16 | 17 | var toMailFolder = outlookProvider.Folders.FirstOrDefault(f => f.FolderPath == @"\\account\Mailbox Archive"); 18 | 19 | var oldMails = mailItems.Where(m => m.ReceivedTime >= DateTime.Today.AddYears(-1)); 20 | 21 | while (oldMails.Count() > 0) 22 | { 23 | var mail = oldMails.Last(); 24 | //mail.Delete(); 25 | //mail.Move(toMailFolder); 26 | } 27 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Stefan Cruysberghs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/IOneNoteProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.Office.Interop.OneNote; 3 | 4 | namespace ScipBe.Common.Office.OneNote 5 | { 6 | public interface IOneNoteProvider 7 | { 8 | /// 9 | /// Instance of OneNote Application object. 10 | /// 11 | Application OneNote { get; } 12 | 13 | /// 14 | /// Hierarchy of Notebooks with Sections and Pages. 15 | /// 16 | IEnumerable NotebookItems { get; } 17 | 18 | /// 19 | /// Collection of Pages. 20 | /// 21 | IEnumerable PageItems { get; } 22 | 23 | /// 24 | /// Returns a list of pages that match the specified query term. 25 | /// 26 | /// The search string. Pass exactly the same string that you would type into the search box in the OneNote UI. 27 | /// You can use bitwise operators, such as AND and OR, which must be all uppercase. 28 | IEnumerable FindPages(string searchString); 29 | } 30 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/IOneNotePage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ScipBe.Common.Office.OneNote 4 | { 5 | /// 6 | /// Page in OneNote. 7 | /// 8 | public interface IOneNotePage 9 | { 10 | /// 11 | /// ID of Page. 12 | /// 13 | string ID { get; } 14 | 15 | /// 16 | /// Name of Page. 17 | /// 18 | string Name { get; } 19 | 20 | /// 21 | /// Level of page. 22 | /// 23 | int Level { get; } 24 | 25 | /// 26 | /// Date and time of creation of the Page. 27 | /// 28 | DateTime DateTime { get; } 29 | 30 | /// 31 | /// Date and time of last modification of Page. 32 | /// 33 | DateTime LastModified { get; } 34 | 35 | /// 36 | /// Gets page content as an xml string. 37 | /// 38 | string GetContent(); 39 | 40 | /// 41 | /// Open this page in the OneNote app. 42 | /// 43 | void OpenInOneNote(); 44 | 45 | } 46 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Tests/ScipBe.Common.Office.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Always 30 | 31 | 32 | Always 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Doc/LinqPad/ScipBe.Common.Office.Outlook - Appointments.linq: -------------------------------------------------------------------------------- 1 | 2 | ScipBe.Common.Office.Outlook 3 | Microsoft.Office.Interop.Outlook 4 | ScipBe.Common.Office 5 | ScipBe.Common.Office.Outlook 6 | 7 | 8 | void Main() 9 | { 10 | Util.RawHtml($"

ScipBe.Common.Office.Outlook - LINQ to Outlook - Query Appointments

").Dump(); 11 | 12 | var outlookProvider = new OutlookProvider(); 13 | 14 | var apointmentItems = outlookProvider.CalendarItems; 15 | //var apointmentItems = outlookProvider.GetItems(@"\\account\Agenda"); 16 | 17 | var query = 18 | from a in apointmentItems 19 | where a.Start >= DateTime.Today.AddMonths(-1) 20 | //where a.IsRecurring 21 | //where a.Subject != null 22 | //where a.Subject.Contains("Brown bag session") 23 | //where a.Categories.Contains("Sport") 24 | //where a.Start != a.End 25 | select new 26 | { 27 | a.Start, 28 | a.End, 29 | a.Duration, 30 | a.Subject, 31 | a.IsRecurring, 32 | a.ReminderSet, 33 | a.ReminderMinutesBeforeStart, 34 | a.Organizer, 35 | a.Location, 36 | a.Categories 37 | }; 38 | 39 | query.Dump("Outlook Appointments"); 40 | } -------------------------------------------------------------------------------- /Doc/LinqPad/ScipBe.Common.Office.Excel - Persons.linq: -------------------------------------------------------------------------------- 1 | 2 | ScipBe.Common.Office.Excel 3 | ScipBe.Common.Office.Excel 4 | 5 | 6 | void Main() 7 | { 8 | Util.RawHtml($"

ScipBe.Common.Office.Excel - LINQ to Excel - Load Excel worksheet or CSV file

").Dump(); 9 | 10 | var excel = new ExcelProvider($@"{Path.GetDirectoryName(Util.CurrentQueryPath)}\Persons.xlsx", "Persons"); 11 | //var excel = new ExcelProvider($@"{Path.GetDirectoryName(Util.CurrentQueryPath)}\Persons.xls", "Persons"); 12 | 13 | excel.Columns.Dump("Columns"); 14 | 15 | var query = 16 | from r in excel.Rows 17 | select new 18 | { 19 | ID = r[1], 20 | ID2 = r["A"], 21 | ID3 = r.Get(1), 22 | ID4 = r.Get(1), 23 | ID5 = r.Get("A"), 24 | ID6 = r.Get("A"), 25 | ID7 = r.GetByName("ID"), 26 | ID8 = r.GetByName("ID"), 27 | FirstName = r[2], 28 | LastName = r.Get(3), 29 | Country = r.GetByName("Country"), 30 | BirthDate = r.Get(5), 31 | BirthDate2 = r[5].ToString(), 32 | BirthDate3 = r["E"], 33 | BirthDate4 = r.GetByName("BirthDate"), 34 | BirthDate5 = r.Get("E"), 35 | BirthDate6 = r.GetByName("BirthDate").AddMonths(1), 36 | Row = r.ToString() 37 | }; 38 | 39 | query.Dump("Rows"); 40 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Utils/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ScipBe.Common.Office.Utils 4 | { 5 | public static class StringExtensions 6 | { 7 | /// 8 | /// Convert the string representation of a number to its 32-bit signed integer equivalent. 9 | /// 10 | /// String containing a number to convert. 11 | /// System.Int32. 12 | /// 13 | /// The conversion fails if the string parameter is null, is not of the correct format, or represents a number 14 | /// less than System.Int32.MinValue or greater than System.Int32.MaxValue. 15 | /// 16 | public static int ToInt32(this string value) 17 | { 18 | return int.TryParse(value, out int number) ? number : default; 19 | } 20 | 21 | /// 22 | /// Convert the string representation of a date time. 23 | /// 24 | /// String containing a date time to convert. 25 | /// System.DateTime. 26 | public static DateTime ToDateTime(this string value) 27 | { 28 | return DateTime.TryParse(value, out DateTime dateTime) 29 | ? dateTime 30 | : DateTime.MinValue; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.OneNote/ScipBe.Common.Office.OneNote.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ScipBe.Common.Office.OneNote 5 | 3.1.1 6 | Stefan Cruysberghs 7 | LINQ to OneNote. Query Notebooks, Sections and Pages. 8 | The OneNoteProvider provides collections of Notebooks, Sections and Pages by parsing the XML hierarchy tree of OneNote. 9 | en-US 10 | https://github.com/scipbe/ScipBe-Common-Office 11 | MIT 12 | Images\ScipBe.Common.Office.OneNote.png 13 | 14 | Version 3.1.1 (January 2025) 15 | - Upgraded unit test project to .NET 8.0 in stead of old .NET 4.6 16 | - Updated LinqPad scripts with examples 17 | 18 | scipbe linq office onenote interop notebook section page 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Outlook/OlItemTypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Office.Interop.Outlook; 2 | using System; 3 | 4 | namespace ScipBe.Common.Office.Outlook 5 | { 6 | public static class OlItemTypeExtensions 7 | { 8 | public static Type GetItemType(this OlItemType olItemType) 9 | { 10 | switch (olItemType) 11 | { 12 | case OlItemType.olMailItem: 13 | return typeof(MailItem); 14 | case OlItemType.olAppointmentItem: 15 | return typeof(AppointmentItem); 16 | case OlItemType.olContactItem: 17 | return typeof(ContactItem); 18 | case OlItemType.olTaskItem: 19 | return typeof(TaskItem); 20 | case OlItemType.olJournalItem: 21 | return typeof(JournalItem); 22 | case OlItemType.olNoteItem: 23 | return typeof(NoteItem); 24 | case OlItemType.olPostItem: 25 | return typeof(PostItem); 26 | case OlItemType.olDistributionListItem: 27 | return typeof(DistListItem); 28 | case OlItemType.olMobileItemSMS: 29 | return typeof(MobileItem); 30 | case OlItemType.olMobileItemMMS: 31 | return typeof(MobileItem); 32 | default: 33 | return null; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Doc/LinqPad/ScipBe.Common.Office.Outlook - Contacts.linq: -------------------------------------------------------------------------------- 1 | 2 | ScipBe.Common.Office.Outlook 3 | Microsoft.Office.Interop.Outlook 4 | ScipBe.Common.Office 5 | ScipBe.Common.Office.Outlook 6 | 7 | 8 | void Main() 9 | { 10 | Util.RawHtml($"

ScipBe.Common.Office.Outlook - LINQ to Outlook - Query Contacts

").Dump(); 11 | 12 | var outlookProvider = new OutlookProvider(); 13 | 14 | var contactItems = outlookProvider.ContactItems; 15 | //var contactItems = outlook.GetItems(@"\\account\Contactpersons"); 16 | 17 | var query = 18 | from c in contactItems 19 | //where c.Email1Address == null 20 | //where c.Attachments.OfType().Count() > 0 21 | //where c.LastName == "" 22 | //where (c.Body != null) && (c.Body.Contains("Son of")) 23 | //where c.Categories != null && c.Categories.Contains("Computerclub") 24 | select new 25 | { 26 | c.FirstName, 27 | c.LastName, 28 | c.HomeAddress, 29 | c.HomeAddressStreet, 30 | c.HomeAddressPostalCode, 31 | c.HomeAddressCity, 32 | c.HomeAddressCountry, 33 | c.BusinessAddress, 34 | c.BusinessAddressStreet, 35 | c.BusinessAddressPostalCode, 36 | c.BusinessAddressCity, 37 | c.BusinessAddressCountry, 38 | c.Email1Address, 39 | c.Email2Address, 40 | c.WebPage, 41 | c.HasPicture, 42 | c.HomeTelephoneNumber, 43 | c.MobileTelephoneNumber, 44 | c.BusinessTelephoneNumber, 45 | c.Categories 46 | }; 47 | 48 | query.Dump("Outlook Contacts"); 49 | } -------------------------------------------------------------------------------- /Doc/LinqPad/ScipBe.Common.Office.Outlook - Mails - Delete attachments.linq: -------------------------------------------------------------------------------- 1 | 2 | ScipBe.Common.Office.Outlook 3 | Microsoft.Office.Interop.Outlook 4 | ScipBe.Common.Office.Outlook 5 | 6 | 7 | void Main() 8 | { 9 | Util.RawHtml($"

ScipBe.Common.Office.Outlook - LINQ to Outlook - Remove large Attachments from Mails

").Dump(); 10 | 11 | var outlookProvider = new OutlookProvider(); 12 | 13 | var mails = outlookProvider.InboxItems; 14 | //var mails = outlookProvider.SentMailItems; 15 | //var mails = outlookProvider.GetItems(@"\\account\Mailbox OUT"); 16 | 17 | var maxSizeInKb = 1024 * 500; 18 | 19 | var mailsWithAttachments = 20 | from m in mails 21 | let a = m.Attachments.OfType() 22 | where 23 | m.Attachments.Count > 0 24 | && m.Attachments.OfType().Any(a => a.Size > maxSizeInKb) 25 | select m; 26 | 27 | ((mailsWithAttachments.Sum(m => m.Attachments.OfType().Sum(a => a.Size)) / 1024 / 1024) + "MB").Dump("Total size of attachments which will be deleted"); 28 | 29 | foreach (var mail in mailsWithAttachments) 30 | { 31 | foreach (var attachment in mail.Attachments.OfType().Where(a => a.Size > maxSizeInKb)) 32 | { 33 | $"{mail.CreationTime} - {mail.Subject} - {attachment.DisplayName} - {attachment.Size / 1024}KB".Dump(); 34 | mail.Attachments.Remove(attachment.Index); 35 | //mail.Save(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Excel/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ScipBe.Common.Office.Excel")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ScipBe.Common.Office.Excel")] 13 | [assembly: AssemblyCopyright("Copyright © 2025")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b463d0cb-8ee1-4d64-96fa-d74eaaa4a83f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("3.1.1.0")] 36 | [assembly: AssemblyFileVersion("3.1.1.0")] 37 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.OneNote/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ScipBe.Common.Office.OneNote")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ScipBe.Common.Office.OneNote")] 13 | [assembly: AssemblyCopyright("Copyright © 2025")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("028c2546-1fe2-43c8-b27e-c61c4cb4893a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("3.1.1.0")] 36 | [assembly: AssemblyFileVersion("3.1.1.0")] 37 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Outlook/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ScipBe.Common.Office.Outlook")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ScipBe.Common.Office.Outlook")] 13 | [assembly: AssemblyCopyright("Copyright © 2025")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1894c924-b24a-4d92-8567-02e12958fc92")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("3.1.1.0")] 36 | [assembly: AssemblyFileVersion("3.1.1.0")] 37 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Outlook/ScipBe.Common.Office.Outlook.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | Library 5 | false 6 | 7 | 8 | 1591 9 | bin\Debug\ScipBe.Common.Office.Outlook.xml 10 | 11 | 12 | 13 | ContactItemExtensions.cs 14 | 15 | 16 | IOutlookProvider.cs 17 | 18 | 19 | OlItemTypeExtensions.cs 20 | 21 | 22 | OutlookProvider.cs 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Always 35 | 36 | 37 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Utils/Util.cs: -------------------------------------------------------------------------------- 1 | namespace ScipBe.Common.Office.Utils 2 | { 3 | using System; 4 | using System.Threading; 5 | 6 | public static class Util 7 | { 8 | /// 9 | /// Do retry and return some value 10 | /// 11 | /// Return type 12 | /// Type of exception to catch 13 | /// Action to perform 14 | /// Interval between retries 15 | /// How many times to retry 16 | /// Action to call on retry 17 | /// Action return 18 | public static TRet TryCatchAndRetry(Func action, TimeSpan retryInterval, int retryCount, Action onRetry = null) 19 | where TException : Exception 20 | { 21 | int attempt = 0; 22 | while (true) 23 | { 24 | try 25 | { 26 | return action(); 27 | } 28 | catch (TException ex) 29 | { 30 | if (attempt++ < retryCount) 31 | { 32 | onRetry(ex); 33 | Thread.Sleep(retryInterval); 34 | } 35 | else 36 | { 37 | throw; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ScipBe.Common.Office")] 9 | [assembly: AssemblyDescription("Linq to Excel, Outlook and OneNote")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Stefan Cruysberghs, http://www.scip.be")] 12 | [assembly: AssemblyProduct("ScipBe.Common.Office")] 13 | [assembly: AssemblyCopyright("Copyright © 2025")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9e34abb8-cd4c-4489-ba7f-e257d7c170b6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("3.1.1.0")] 36 | [assembly: AssemblyFileVersion("3.1.1.0")] -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Excel/ScipBe.Common.Office.Excel.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ScipBe.Common.Office.Excel 5 | 3.1.1 6 | Stefan Cruysberghs 7 | LINQ to Excel. Query Excel worksheets and CSV files. 8 | The ExcelProvider loads an Excel worksheet and provides column definitions and row collections. All collections are IEnumerable so you can query them with LINQ. The ExcelProvider supports XLSX (Excel 2007-2019, v12-v16), XLS (Excel 97-2003, v8-v11) but it requires the installation of the Microsoft Access Database Engine 2016 Redistributable. 9 | en-US 10 | https://github.com/scipbe/ScipBe-Common-Office 11 | MIT 12 | Images\ScipBe.Common.Office.Excel.png 13 | 14 | Version 3.1.1 (January 2025) 15 | - Switched to Microsoft Access Database Engine 2016 Redistributable for reading Excel XLSX and XLS files 16 | - Removed the support for reading CSV files. The CSVHelper library is a much beter alternative: https://joshclose.github.io/CsvHelper/ 17 | - Upgraded unit test project to .NET 8.0 in stead of old .NET 4.6 18 | - Updated LinqPad scripts with examples 19 | 20 | scipbe linq office excel ado xlsx xls worksheet 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Doc/LinqPad/ScipBe.Common.Office.OneNote.linq: -------------------------------------------------------------------------------- 1 | 2 | ScipBe.Common.Office.OneNote 3 | Microsoft.Office.Interop.OneNote 4 | ScipBe.Common.Office.OneNote 5 | 6 | 7 | void Main() 8 | { 9 | Util.RawHtml($"

ScipBe.Common.Office.OneNote - LINQ to OneNote - Query Notebooks, Sections and Pages

").Dump(); 10 | 11 | // Show all encrypted OneNote Notebooks 12 | var queryEncryptedSections = 13 | from nb in OneNoteProvider.NotebookItems 14 | from s in nb.Sections 15 | where s.Encrypted == true 16 | select new { NotebookName = nb.Name, SectionName = s.Name }; 17 | queryEncryptedSections.Dump("All encrypted OneNote Notebooks"); 18 | 19 | // Show all OneNote Notebooks and the number of Sections they have 20 | var queryNotebooks = 21 | (from nb in OneNoteProvider.NotebookItems 22 | select new { Notebook = nb.Name, SectionCount = nb.Sections.Count() }) 23 | .OrderByDescending(n => n.SectionCount); 24 | queryNotebooks.Dump("All OneNote Notebooks and the number of Sections they have"); 25 | 26 | // Show all OneNote Pages which have been modified last few days 27 | var queryPages = 28 | from page in OneNoteProvider.PageItems 29 | where page.LastModified > DateTime.Now.AddDays(-2) 30 | orderby page.LastModified descending 31 | select page; 32 | queryPages.Dump("All OneNote Pages which have been modified last few days"); 33 | 34 | // Show XML content of the OneNote Pages which have been changed the last few days 35 | foreach (var item in OneNoteProvider.PageItems.Where(p => p.LastModified > DateTime.Now.AddDays(-2))) 36 | { 37 | item.GetContent().Dump($"{item.LastModified} {item.Notebook.Name} {item.Section.Name} {item.Name} {item.DateTime}"); 38 | } 39 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Outlook/ScipBe.Common.Office.Outlook.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ScipBe.Common.Office.Outlook 5 | 3.1.1 6 | Stefan Cruysberghs 7 | LINQ to Outlook. Query Outlook Mails, Appointments, Contacts, ... 8 | The OutlookProvider is a wrapper class which provides collections to data of Outlook (AppointmentItems, ContactItems, MailItems, TaskItems, ...). The OutlookProvider exposes collections of classes of the Microsoft.Office.Interop.Outlook assembly so you have full access to all properties and it also supports adding, updating and deleting data in Outlook. 9 | en-US 10 | https://github.com/scipbe/ScipBe-Common-Office 11 | MIT 12 | Images\ScipBe.Common.Office.Outlook.png 13 | 14 | Version 3.1.1 (January 2025) 15 | - Updated Microsoft Office Outlook Interop nuget package to latest version 15.0.4797.1003 16 | - Upgraded unit test project to .NET 8.0 in stead of old .NET 4.6 17 | - Updated LinqPad scripts with examples 18 | 19 | scipbe linq office outlook interop mail contact appointment calendar agenda 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Excel/IExcelProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ScipBe.Common.Office.Excel 4 | { 5 | public interface IExcelProvider 6 | { 7 | /// 8 | /// File name of Excel XLSX/XLS or CSV file. 9 | /// 10 | string FileName { get; } 11 | 12 | /// 13 | /// Type of File: XLSX, XLS or CSV. 14 | /// 15 | FileType FileType { get; } 16 | 17 | /// 18 | /// Name of worksheet. 19 | /// 20 | string SheetName { get; } 21 | 22 | /// 23 | /// Collection of definitions of Excel columns. 24 | /// 25 | List Columns { get; } 26 | 27 | /// 28 | /// Collection of Excel rows. 29 | /// 30 | List Rows { get; } 31 | 32 | /// 33 | /// Load XLSX, XLS or CSV file of given worksheet. 34 | /// 35 | /// Name of XLSX, XLS or CSV file. 36 | /// Name of worksheet. Required for XLS or XLSX file. Can be empty for CSV file. 37 | /// 38 | /// The file name of the CSV file should not contains spaces. 39 | /// The first row of CSV file needs a to contain the column names. 40 | /// The delimiter of the CSV can be specified in the registry at the following location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Text. 41 | /// Format can be "TabDelimited", "CSVDelimited" or "Delimited(;)". 42 | /// Or create a schema.ini file in the same folder as the CSV file where you specify the delimiter. 43 | /// 44 | void Load(string fileName, string sheetName = null); 45 | } 46 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Tests/OneNote/OneNoteProviderTest.cs: -------------------------------------------------------------------------------- 1 | using ScipBe.Common.Office.OneNote; 2 | 3 | namespace ScipBe.Common.Office.Tests 4 | { 5 | [TestClass] 6 | public class OneNoteProviderTest 7 | { 8 | [TestMethod] 9 | public void Notebooks() 10 | { 11 | // Act 12 | var notebooks = OneNoteProvider.NotebookItems; 13 | 14 | // Arrange 15 | Assert.IsTrue(notebooks.Count() > 0); 16 | } 17 | 18 | [TestMethod] 19 | public void Pages() 20 | { 21 | // Act 22 | var pages = OneNoteProvider.PageItems; 23 | 24 | // Arrange 25 | Assert.IsTrue(pages.Count() > 0); 26 | } 27 | 28 | [TestMethod] 29 | public void EnumerateSections() 30 | { 31 | // Act 32 | var sections = OneNoteProvider.NotebookItems.SelectMany(n => n.Sections); 33 | 34 | // Arrange 35 | Assert.IsTrue(sections.Count() > 0); 36 | } 37 | 38 | [TestMethod] 39 | public void FindPages() 40 | { 41 | // Act 42 | var pages = OneNoteProvider.FindPages("the"); 43 | 44 | // Arrange 45 | Assert.IsTrue(pages.Count() > 0); 46 | } 47 | 48 | [TestMethod] 49 | public void GetContent() 50 | { 51 | // Act 52 | var page = OneNoteProvider.PageItems.First(); 53 | string content = page.GetContent(); 54 | 55 | // Arrange 56 | Assert.IsFalse(string.IsNullOrWhiteSpace(content)); 57 | } 58 | 59 | [TestMethod] 60 | public void OpenInOneNote() 61 | { 62 | // Act 63 | var page = OneNoteProvider.PageItems.First(); 64 | page.OpenInOneNote(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Excel/ScipBe.Common.Office.Excel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | Library 5 | false 6 | 7 | 8 | 1591 9 | bin\Debug\ScipBe.Common.Office.Excel.xml 10 | 11 | 12 | 13 | ExcelColumn.cs 14 | 15 | 16 | ExcelProvider.cs 17 | 18 | 19 | ExcelRow.cs 20 | 21 | 22 | FileType.cs 23 | 24 | 25 | IExcelColumn.cs 26 | 27 | 28 | IExcelProvider.cs 29 | 30 | 31 | IExcelRow.cs 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | Always 44 | 45 | 46 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Tests/Excel/ExcelProvidertTest.cs: -------------------------------------------------------------------------------- 1 | using ScipBe.Common.Office.Excel; 2 | 3 | namespace ScipBe.Common.Office.Tests 4 | { 5 | [TestClass] 6 | public class ExcelProvidertTest 7 | { 8 | [TestMethod] 9 | public void LoadXlsxFile() 10 | { 11 | var fileName = $@"{AppDomain.CurrentDomain.BaseDirectory}\Excel\Persons.xlsx"; 12 | LoadFile(fileName, "Persons"); 13 | } 14 | 15 | [TestMethod] 16 | public void LoadXlsFile() 17 | { 18 | var fileName = $@"{AppDomain.CurrentDomain.BaseDirectory}\Excel\Persons.xls"; 19 | LoadFile(fileName, "Persons"); 20 | } 21 | 22 | private void LoadFile(string fileName, string workSheetName = null) 23 | { 24 | var excel = new ExcelProvider(fileName, workSheetName); 25 | 26 | Assert.AreEqual(5, excel.Columns.Count()); 27 | 28 | Assert.AreEqual(1, excel.Columns.First().Index); 29 | Assert.AreEqual("A", excel.Columns.First().Header); 30 | Assert.AreEqual("ID", excel.Columns.First().Name); 31 | 32 | Assert.AreEqual(5, excel.Columns.Last().Index); 33 | Assert.AreEqual("E", excel.Columns.Last().Header); 34 | Assert.AreEqual("BirthDate", excel.Columns.Last().Name); 35 | 36 | Assert.AreEqual(5, excel.Rows.Count()); 37 | 38 | Assert.AreEqual(5, excel.Rows.Last().Index); 39 | Assert.AreEqual(5, excel.Rows.Last().Get(1)); 40 | Assert.AreEqual(5, excel.Rows.Last().Get("A")); 41 | Assert.AreEqual(5, excel.Rows.Last().GetByName("ID")); 42 | 43 | Assert.AreEqual("Peter", excel.Rows.Last().Get(2)); 44 | Assert.AreEqual("Peter", excel.Rows.Last().Get("B")); 45 | Assert.AreEqual("Peter", excel.Rows.Last().GetByName("FirstName")); 46 | 47 | Assert.AreEqual(DateTime.Parse("1979-05-03 0:00:00"), excel.Rows.Last().GetByName("BirthDate")); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Outlook/ContactItemExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Office.Interop.Outlook; 2 | using System.Diagnostics; 3 | using System.IO; 4 | 5 | namespace ScipBe.Common.Office.Outlook 6 | { 7 | public static class ContactItemExtensions 8 | { 9 | 10 | /// 11 | /// Save contact picture as JPG in given folder and return path to this file. 12 | /// 13 | /// Outlook contact item. 14 | /// Path to folder with temporary Outlook contact pictures. 15 | /// Path to JPG file with Outlook contact picture. 16 | public static string GetContactPicturePath(this ContactItem contact, string path) 17 | { 18 | string picturePath = ""; 19 | 20 | if (contact.HasPicture) 21 | { 22 | foreach (Attachment att in contact.Attachments) 23 | { 24 | if (att.DisplayName == "ContactPicture.jpg") 25 | { 26 | try 27 | { 28 | picturePath = Path.GetDirectoryName(path) + "\\Contact_" + contact.EntryID + ".jpg"; 29 | if (!File.Exists(picturePath)) 30 | { 31 | att.SaveAsFile(picturePath); 32 | } 33 | } 34 | catch (IOException ex) 35 | { 36 | picturePath = ""; 37 | Debug.Write(ex.Message); 38 | } 39 | } 40 | } 41 | } 42 | 43 | return picturePath; 44 | } 45 | 46 | /// 47 | /// Save contact picture as JPG in Windows temporary folder and return path to this file. 48 | /// 49 | /// Outlook contact item. 50 | /// Path to JPG file with Outlook contact picture. 51 | public static string GetContactPicturePath(ContactItem contact) 52 | { 53 | return contact.GetContactPicturePath(Path.GetTempPath()); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Excel/IExcelRow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ScipBe.Common.Office.Excel 4 | { 5 | /// 6 | /// Interface for row with cell values of Excel worksheet. 7 | /// 8 | public interface IExcelRow 9 | { 10 | /// 11 | /// Row index, 1 - 999999. 12 | /// 13 | int Index { get; } 14 | 15 | /// 16 | /// Get cell value as Object. Column index is given. 17 | /// 18 | /// Column index, starts with 1. 19 | /// Value of cell as Object. 20 | Object this[int columnIndex] { get; } 21 | 22 | /// 23 | /// Get cell value as Object. Column header is given. 24 | /// 25 | /// Column header, starts with A. 26 | /// Value of cell as Object. 27 | Object this[string columnHeader] { get; } 28 | 29 | /// 30 | /// Get cell value as given class type. Column index is given. 31 | /// 32 | /// Class type of cell value 33 | /// Column index, starts with 1. 34 | /// Value of cell 35 | T Get(int columnIndex); 36 | 37 | /// 38 | /// Get cell value as given class type. Column header is given. 39 | /// 40 | /// Class type of cell value. 41 | /// Column headers, starts with A. 42 | /// Value of cell 43 | T Get(string columnHeader); 44 | 45 | /// 46 | /// Get cell value as given class type. Column name (from first row) is given. 47 | /// 48 | /// Class type of cell value. 49 | /// Column name, is string name in first row of Excel worksheet. 50 | /// Value of cell 51 | T GetByName(string columnName); 52 | 53 | /// 54 | /// Get string representation of row. 55 | /// 56 | /// Comma seperated list of all cell values. 57 | string ToString(); 58 | } 59 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/ScipBe.Common.Office.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | Library 5 | SAK 6 | SAK 7 | SAK 8 | SAK 9 | publish\ 10 | true 11 | Disk 12 | false 13 | Foreground 14 | 7 15 | Days 16 | false 17 | false 18 | true 19 | 0 20 | 1.0.0.%2a 21 | false 22 | false 23 | true 24 | false 25 | 26 | 27 | bin\Debug\ScipBe.Common.Office.XML 28 | 1591 29 | 30 | 31 | 32 | 3.5 33 | 34 | 35 | 3.5 36 | 37 | 38 | 39 | 40 | Designer 41 | 42 | 43 | Always 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/ScipBe.Common.Office.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ScipBe.Common.Office 5 | 3.1.1 6 | Stefan Cruysberghs 7 | LINQ to Excel, LINQ to Outlook and LINQ to OneNote. Query data of Excel worksheets, Outlook Mails, Appointments, Contacts, ... and OneNote Notebooks, Sections and Pages. 8 | The ScipBe.Common.Office namespace contains 3 classes: ExcelProvider (LINQ to Excel), OutlookProvider (LINQ to Outlook) and OneNoteProvider (LINQ to OneNote). The ExcelProvider loads an Excel worksheet or CSV file and provides column definition and row collections. The OutlookProvider is a wrapper class which provides collections to data of Outlook (AppointmentItems, ContactItems, MailItems, TaskItems, ...). The OneNoteProvider provides collections of Notebooks, Sections and Pages by parsing the XML hierarchy tree of OneNote. All collections are IEnumerable so you can query them with LINQ. There are also 3 separated NuGet packages with for the Excel, Outlook and OneNote provider so they can be used standalone. 9 | en-US 10 | https://github.com/scipbe/ScipBe-Common-Office 11 | MIT 12 | Images\ScipBe.Common.Office.png 13 | 14 | Version 3.1.1 (January 2025) 15 | - Switched to Microsoft Access Database Engine 2016 Redistributable for reading Excel XLSX and XLS files 16 | - Removed the support for reading CSV files. The CSVHelper library is a much beter alternative: https://joshclose.github.io/CsvHelper/ 17 | - Updated Microsoft Office Outlook Interop nuget package to latest version 15.0.4797.1003 18 | - Upgraded unit test project to .NET 8.0 in stead of old .NET 4.6 19 | - Updated LinqPad scripts with examples 20 | 21 | scipbe linq office excel outlook onenote interop 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Class diagrams/ExcelProvider.cd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | AAAAggAAQAIAAEAAAADAAAwEAAAABAAACEAAAAhAAAA= 25 | Excel\ExcelProvider.cs 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | BAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQEAAAAAAAA= 40 | Excel\IExcelColumn.cs 41 | 42 | 43 | 44 | 45 | 46 | AAAAAAAAAAAAAABECAAAAAAAAAAAAAAAAAEAAAAAAAg= 47 | Excel\IExcelRow.cs 48 | 49 | 50 | 51 | 52 | 53 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAAAEAAAAAAAAA= 54 | Excel\FileType.cs 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Outlook/IOutlookProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.Office.Interop.Outlook; 3 | 4 | namespace ScipBe.Common.Office.Outlook 5 | { 6 | public interface IOutlookProvider 7 | { 8 | /// 9 | /// Instance of Outlook Application object. 10 | /// 11 | Application Outlook { get; } 12 | 13 | /// 14 | /// Collection of Folder items. 15 | /// The Outlook class holds a hierarchical structure of folders. 16 | /// This property will flatten this hierarchy and return a collection with all folders. 17 | /// 18 | IEnumerable Folders { get; } 19 | 20 | /// 21 | /// Get Outlook items of a given folder. 22 | /// 23 | /// Type (AppointmentItem, ContactItem, JournalItem, MailItem, NoteItem, PostItem, TaskItem). 24 | /// Outlook folder. 25 | IEnumerable GetItems(Folder folder); 26 | 27 | /// 28 | /// Get Outlook items of a given folder path. 29 | /// 30 | /// Type (AppointmentItem, ContactItem, JournalItem, MailItem, NoteItem, PostItem, TaskItem). 31 | /// Outlook folder path. 32 | /// Collection of items (AppointmentItems, ContactItems, MailItems, ...). 33 | IEnumerable GetItems(string folderPath); 34 | 35 | /// 36 | /// Collection of Contact Items of default Contacts folder. 37 | /// 38 | IEnumerable ContactItems { get; } 39 | 40 | /// 41 | /// Collection of Appointment (Calendar) Items of default Calendar. 42 | /// 43 | IEnumerable CalendarItems { get; } 44 | 45 | /// 46 | /// Collection of Mail Items of default Inbox folder. 47 | /// 48 | IEnumerable InboxItems { get; } 49 | 50 | /// 51 | /// Collection of Mail Items of default SendMail folder. 52 | /// 53 | IEnumerable SentMailItems { get; } 54 | 55 | /// 56 | /// Collection of Note Items of default Notes folder. 57 | /// 58 | IEnumerable NoteItems { get; } 59 | 60 | /// 61 | /// Collection of Task Items of default Tasks folder. 62 | /// 63 | IEnumerable TaskItems { get; } 64 | 65 | } 66 | } -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.Tests/Outlook/OutlookProvidertTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Office.Interop.Outlook; 2 | using ScipBe.Common.Office.Outlook; 3 | 4 | namespace ScipBe.Common.Office.Tests 5 | { 6 | [TestClass] 7 | public class OutlookProvidertTest 8 | { 9 | [TestMethod] 10 | public void Folders() 11 | { 12 | // Arrange 13 | var outlook = new OutlookProvider(); 14 | 15 | // Act 16 | var folders = outlook.Folders; 17 | 18 | // Assert 19 | Assert.IsTrue(outlook.Folders.Any()); 20 | } 21 | 22 | [TestMethod] 23 | public void ContactItems() 24 | { 25 | // Arrange 26 | var outlook = new OutlookProvider(); 27 | 28 | // Act 29 | var contactItems = outlook.ContactItems; 30 | 31 | // Assert 32 | Assert.IsTrue(contactItems.Any()); 33 | } 34 | 35 | [TestMethod] 36 | public void CalendarItems() 37 | { 38 | // Arrange 39 | var outlook = new OutlookProvider(); 40 | 41 | // Act 42 | var calendarItems = outlook.CalendarItems; 43 | 44 | // Assert 45 | Assert.IsTrue(calendarItems.Any()); 46 | } 47 | 48 | [TestMethod] 49 | public void InboxItems() 50 | { 51 | // Arrange 52 | var outlook = new OutlookProvider(); 53 | 54 | // Act 55 | var inboxItems = outlook.InboxItems; 56 | 57 | // Assert 58 | Assert.IsTrue(inboxItems.Any()); 59 | } 60 | 61 | [TestMethod] 62 | public void SentMailItems() 63 | { 64 | // Arrange 65 | var outlook = new OutlookProvider(); 66 | 67 | // Act 68 | var sentMailItems = outlook.SentMailItems; 69 | 70 | // Assert 71 | Assert.IsTrue(sentMailItems.Any()); 72 | } 73 | 74 | [TestMethod] 75 | public void GetItemsByFolder() 76 | { 77 | // Arrange 78 | var outlook = new OutlookProvider(); 79 | 80 | // Act 81 | var folder = outlook.Folders.FirstOrDefault(f => f.Items.Count > 0 && f.DefaultItemType == OlItemType.olMailItem); 82 | var mailItems = outlook.GetItems(folder); 83 | 84 | // Assert 85 | Assert.IsTrue(mailItems.Any()); 86 | } 87 | 88 | [TestMethod] 89 | public void GetItemByFolderPath() 90 | { 91 | // Arrange 92 | var outlook = new OutlookProvider(); 93 | 94 | // Act 95 | var folder = outlook.Folders.FirstOrDefault(f => f.Items.Count > 0 && f.DefaultItemType == OlItemType.olAppointmentItem); 96 | var appointmentItems = outlook.GetItems(folder.FolderPath); 97 | 98 | // Assert 99 | Assert.IsTrue(appointmentItems.Any()); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.OneNote/ScipBe.Common.Office.OneNote.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | Library 5 | false 6 | 7 | 8 | bin\Debug\ScipBe.Common.Office.OneNote.xml 9 | 1591 10 | 11 | 12 | 13 | IOneNoteExtNotebook.cs 14 | 15 | 16 | IOneNoteExtPage.cs 17 | 18 | 19 | IOneNoteExtSection.cs 20 | 21 | 22 | IOneNoteNotebook.cs 23 | 24 | 25 | IOneNotePage.cs 26 | 27 | 28 | IOneNoteProvider.cs 29 | 30 | 31 | IOneNoteSection.cs 32 | 33 | 34 | OneNoteExtNotebook.cs 35 | 36 | 37 | OneNoteExtPage.cs 38 | 39 | 40 | OneNoteExtSection.cs 41 | 42 | 43 | OneNoteNotebook.cs 44 | 45 | 46 | OneNotePage.cs 47 | 48 | 49 | OneNoteProvider.cs 50 | 51 | 52 | OneNoteSection.cs 53 | 54 | 55 | StringExtensions.cs 56 | 57 | 58 | StringExtensions.cs 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | Always 71 | 72 | 73 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.35431.28 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScipBe.Common.Office", "ScipBe.Common.Office\ScipBe.Common.Office.csproj", "{233D48E6-9618-4861-BD45-683BA450341C}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScipBe.Common.Office.OneNote", "ScipBe.Common.Office.OneNote\ScipBe.Common.Office.OneNote.csproj", "{028C2546-1FE2-43C8-B27E-C61C4CB4893A}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScipBe.Common.Office.Outlook", "ScipBe.Common.Office.Outlook\ScipBe.Common.Office.Outlook.csproj", "{1894C924-B24A-4D92-8567-02E12958FC92}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6F9A40A0-9727-43B1-A525-2E990D93D470}" 13 | ProjectSection(SolutionItems) = preProject 14 | ..\README.md = ..\README.md 15 | EndProjectSection 16 | EndProject 17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScipBe.Common.Office.Excel", "ScipBe.Common.Office.Excel\ScipBe.Common.Office.Excel.csproj", "{B463D0CB-8EE1-4D64-96FA-D74EAAA4A83F}" 18 | EndProject 19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScipBe.Common.Office.Tests", "ScipBe.Common.Office.Tests\ScipBe.Common.Office.Tests.csproj", "{143BE0DD-65F7-4813-BA88-74B139B721B6}" 20 | EndProject 21 | Global 22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 23 | Debug|Any CPU = Debug|Any CPU 24 | Release|Any CPU = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {233D48E6-9618-4861-BD45-683BA450341C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {233D48E6-9618-4861-BD45-683BA450341C}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {233D48E6-9618-4861-BD45-683BA450341C}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {233D48E6-9618-4861-BD45-683BA450341C}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {028C2546-1FE2-43C8-B27E-C61C4CB4893A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {028C2546-1FE2-43C8-B27E-C61C4CB4893A}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {028C2546-1FE2-43C8-B27E-C61C4CB4893A}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {028C2546-1FE2-43C8-B27E-C61C4CB4893A}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {1894C924-B24A-4D92-8567-02E12958FC92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {1894C924-B24A-4D92-8567-02E12958FC92}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {1894C924-B24A-4D92-8567-02E12958FC92}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {1894C924-B24A-4D92-8567-02E12958FC92}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {B463D0CB-8EE1-4D64-96FA-D74EAAA4A83F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {B463D0CB-8EE1-4D64-96FA-D74EAAA4A83F}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {B463D0CB-8EE1-4D64-96FA-D74EAAA4A83F}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {B463D0CB-8EE1-4D64-96FA-D74EAAA4A83F}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {143BE0DD-65F7-4813-BA88-74B139B721B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {143BE0DD-65F7-4813-BA88-74B139B721B6}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {143BE0DD-65F7-4813-BA88-74B139B721B6}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {143BE0DD-65F7-4813-BA88-74B139B721B6}.Release|Any CPU.Build.0 = Release|Any CPU 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Excel/ExcelRow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace ScipBe.Common.Office.Excel 5 | { 6 | internal class ExcelRow : IExcelRow 7 | { 8 | private readonly List columns; 9 | private readonly List cells = new List(); 10 | 11 | public ExcelRow(int index, List columns) 12 | { 13 | Index = index; 14 | this.columns = columns; 15 | } 16 | 17 | internal void AddCell(Object data) 18 | { 19 | cells.Add(data); 20 | } 21 | 22 | private int CheckColumn(int columnIndex) 23 | { 24 | if ((columnIndex > 0) && (columnIndex <= columns.Count)) 25 | return columnIndex - 1; 26 | return -1; 27 | } 28 | 29 | private int CheckColumn(string columnHeader) 30 | { 31 | int columnIndex = columns.FindIndex(c => c.Header == columnHeader); 32 | return columnIndex; 33 | } 34 | 35 | private int CheckColumnByName(string columnName) 36 | { 37 | int columnIndex = columns.FindIndex(c => c.Name == columnName); 38 | return columnIndex; 39 | } 40 | 41 | private static T ConvertTo(object data) 42 | { 43 | try 44 | { 45 | if ((data is DBNull) || (data == null)) 46 | { 47 | return default(T); 48 | } 49 | return (T)Convert.ChangeType(data, typeof(T)); 50 | } 51 | catch 52 | { 53 | return default(T); 54 | } 55 | } 56 | 57 | public int Index { get; internal set; } 58 | 59 | public Object this[int columnIndex] 60 | { 61 | get 62 | { 63 | if (CheckColumn(columnIndex) > -1) 64 | { 65 | return cells[columnIndex - 1]; 66 | } 67 | return null; 68 | } 69 | } 70 | 71 | public Object this[string columnHeader] 72 | { 73 | get 74 | { 75 | int columnIndex = CheckColumn(columnHeader); 76 | if (columnIndex > -1) 77 | { 78 | return cells[columnIndex]; 79 | } 80 | return null; 81 | } 82 | } 83 | 84 | public T Get(int columnIndex) 85 | { 86 | if (CheckColumn(columnIndex) > -1) 87 | { 88 | return ConvertTo(cells[columnIndex - 1]); 89 | } 90 | return default(T); 91 | } 92 | 93 | public T Get(string columnHeader) 94 | { 95 | int columnIndex = CheckColumn(columnHeader); 96 | if (columnIndex > -1) 97 | { 98 | return ConvertTo(cells[columnIndex]); 99 | } 100 | return default(T); 101 | } 102 | 103 | public T GetByName(string columnName) 104 | { 105 | int columnIndex = CheckColumnByName(columnName); 106 | if (columnIndex > -1) 107 | { 108 | return ConvertTo(cells[columnIndex]); 109 | } 110 | return default(T); 111 | } 112 | 113 | public new string ToString() 114 | { 115 | string values = ""; 116 | foreach (var cell in cells) 117 | { 118 | values += ";" + cell.ToString(); 119 | } 120 | return values.Substring(1); 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](Doc/Images/ScipBe.Common.Office.png) 2 | # ScipBe-Common-Office 3 | ### Linq to Excel, Outlook and OneNote 4 | 5 | The ScipBe.Common.Office namespace contains 3 classes: ExcelProvider (LINQ to Excel), OutlookProvider (LINQ to Outlook) and OneNoteProvider (LINQ to OneNote). 6 | - The ExcelProvider loads an Excel worksheet and provides column definitions and row collections. 7 | - The OutlookProvider is a wrapper class which provides collections to data of Outlook (AppointmentItems, ContactItems, MailItems, TaskItems, ...). 8 | - The OneNoteProvider provides collections of Notebooks, Sections and Pages by parsing the XML hierarchy tree of OneNote. 9 | - All collections are IEnumerable so you can query them with LINQ. 10 | - There are also 3 separated projects with only Excel, Outlook and OneNote provider. 11 | 12 | Examples 13 | ================================================================= 14 | 15 | - See scripts in Doc\LinqPad folder 16 | - See class diagrams in Doc\Diagrams folder or in solution 17 | 18 | Links 19 | ================================================================= 20 | 21 | - [Homepage](http://www.scip.be) 22 | - [Documentation and examples](http://www.scip.be/index.php?Page=ComponentsNETOfficeItems) 23 | - [Author Stefan Cruysberghs](http://www.scip.be/index.php?Page=AboutMe) 24 | - [GitHub repository](https://github.com/scipbe/ScipBe-Common-Office) 25 | - [NuGet package Office](https://www.nuget.org/packages/ScipBe.Common.Office) 26 | - [NuGet package Excel](https://www.nuget.org/packages/ScipBe.Common.Office.Excel) 27 | - [NuGet package Outlook](https://www.nuget.org/packages/ScipBe.Common.Office.Outlook) 28 | - [NuGet package OneNote](https://www.nuget.org/packages/ScipBe.Common.Office.OneNote) 29 | 30 | Remarks 31 | ================================================================= 32 | 33 | - ExcelProvider 34 | - The ExcelProvider supports XLSX (Excel 2007-2019, v12-v16), XLS (Excel 97-2003, v8-v11) and CSV (comma, semicolumn or tab delimited ASCII file) files but it requires the installation of the Microsoft Access Database Engine 2016 Redistributable: https://www.microsoft.com/en-us/download/details.aspx?id=54920 35 | 36 | - OutlookProvider 37 | - The OutlookProvider exposes collections of classes of the Microsoft.Office.Interop.Outlook assembly so you have full access to all properties and it also supports adding, updating and deleting data in Outlook. 38 | - This component and the COM Interop approach will only work with classic Outlook (2007-2019) on your PC. If you want to use the new Outlook Windows app or the online Outlook of Office365, then you have to use the Microsoft Graph API to access the data. 39 | 40 | History 41 | ================================================================= 42 | - Version 3.1.0 (January 2025) 43 | - Switched to Microsoft Access Database Engine 2016 Redistributable for reading Excel XLSX and XLS files 44 | - Removed the support for reading CSV files. The CSVHelper library is a much beter alternative: https://joshclose.github.io/CsvHelper/ 45 | - Updated Microsoft Office Interop nuget package to latest version 15.0.4797.1003 46 | - Upgraded unit test project to .NET 8.0 in stead of old .NET 4.6 47 | - Updated LinqPad scripts with examples 48 | - Version 3.0.1 (May 2022) 49 | - Fixed some issues around interacting with the OneNote interop library (#13) 50 | - Version 3.0.0 (May 2022) 51 | - Migrated to .NET Standard 2.0 to allow .NET Core projects to consume (#8) 52 | - Switched OneNoteProvider to be static, and to release the COM interop library around every call, and adding a GetContent() method to PageItem (#11, #3) 53 | - Version 2.0.2 (May 2022) 54 | - Migrated to .NET Standard 2.0 to allow .NET Core projects to consume 55 | - Added FindPages API to OneNoteProvider, and OpenInOneNote method to OneNotePage (#2, #6) 56 | - A couple bug fixes and improvements in the OneNote project and the unit tests (#5) 57 | - Version 2.0 (June 2017) 58 | - Migrated to .NET 4.6 59 | - Fixed some bugfixes and implemented small improvements 60 | - Removed factory method of ExcelProvider and removed ExcelVersion enum 61 | - Moved all classes to subfolders with namespaces Excel, Outlook and OneNote 62 | - Added references to NuGet packages of OneNote interop and Outlook interop 63 | - Released 3 new NuGet packages to use ExcelProvider, OutlookProvider and OneNoteProvider standalone 64 | - Added LinqPad examples 65 | - Version 1.3 (December 2008): .NET 3.5 66 | - Version 1.2 (October 2008): .NET 3.5 67 | - Version 1.1 (December 2007): .NET 3.5 68 | - Version 1.0 (November 2007): .NET 3.5 69 | 70 | License 71 | ================================================================= 72 | 73 | - Released under MIT license -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Class diagrams/OutlookProvider.cd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | AAAAAAAAAIEAAAABAAAAAAEAAIAAAgQAAAADQAAEBAA= 45 | Outlook\OutlookProvider.cs 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Class diagrams/OneNoteProvider.cd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | AAAAAAAAAAAAACAAEAAAAAAIAAAACAAAAAAAAAAAABA= 29 | OneNoteProvider.cs 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA= 45 | OneNoteInterfaces.cs 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | AAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAIAAAAA= 76 | OneNoteInterfaces.cs 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | AAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAA= 98 | OneNoteInterfaces.cs 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | AAAAAAAAAAAAgAIAAAAAAAQAAAAAAAEAAAAAgAAAAAA= 108 | OneNoteInterfaces.cs 109 | 110 | 111 | 112 | 113 | 114 | AAAAAAAAAAAAgAAAAAAAAAQCAAAAAAQAAAAAAAAAAAA= 115 | OneNoteInterfaces.cs 116 | 117 | 118 | 119 | 120 | 121 | AAAAAAAAAAAAgAIAAAAAAAQAAAAAAAAAAAAAgIAAAAA= 122 | OneNoteInterfaces.cs 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | /Doc/Images/Thumbs.db 290 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Excel/ExcelProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.OleDb; 4 | using System.IO; 5 | 6 | namespace ScipBe.Common.Office.Excel 7 | { 8 | /// 9 | /// Excel Provider (LINQ to Excel). 10 | /// 11 | /// 12 | /// 13 | /// Author: Stefan Cruysberghs 14 | /// Website: http://www.scip.be 15 | /// Article: Querying Excel worksheets with LINQ : http://www.scip.be/index.php?Page=ArticlesNET25 16 | /// Microsoft Access Database Engine 2016 Redistributable: https://www.microsoft.com/en-us/download/details.aspx?id=54920 17 | /// 18 | /// 19 | public class ExcelProvider : IExcelProvider 20 | { 21 | /// 22 | /// File name of Excel XLSX or XLS file. 23 | /// 24 | public string FileName { get; private set; } 25 | 26 | /// 27 | /// Type of File: XLSX or XLS. 28 | /// 29 | public FileType FileType { get; private set; } 30 | 31 | /// 32 | /// Name of worksheet. 33 | /// 34 | public string SheetName { get; private set; } 35 | 36 | /// 37 | /// Collection of Excel rows. 38 | /// 39 | public List Rows { get; private set; } = new List(); 40 | 41 | /// 42 | /// Collection of definitions of Excel columns. 43 | /// 44 | 45 | public List Columns { get; private set; } = new List(); 46 | 47 | /// 48 | /// Constructor of ExcelProvider, it will load Excel worksheet or CSV into Rows and Columns collections. 49 | /// 50 | /// Name of XLSX, XLS or CSV file. 51 | /// Name of worksheet. Required for XLS or XLSX file. Can be empty for CSV file. 52 | /// 53 | /// The first row of CSV file needs a to contain the column names. 54 | /// The delimiter of the CSV can be specified in the registry at the following location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Text. 55 | /// Format can be "TabDelimited", "CSVDelimited" or "Delimited(;)". 56 | /// Or create a schema.ini file in the same folder as the CSV file where you specify the delimiter. 57 | /// 58 | public ExcelProvider(string fileName, string sheetName = null) 59 | { 60 | Load(fileName, sheetName); 61 | } 62 | 63 | /// 64 | /// Constructor of ExcelProvider. Call Load afterwards to load worksheet data. 65 | /// 66 | public ExcelProvider() 67 | { 68 | } 69 | 70 | /// 71 | /// Load XLSX, XLS or CSV file of given worksheet. 72 | /// 73 | /// Name of XLSX, XLS or CSV file. 74 | /// Name of worksheet. Required for XLS or XLSX file. Can be empty for CSV file. 75 | /// 76 | /// The file name of the CSV file should not contains spaces. 77 | /// The first row of CSV file needs a to contain the column names. 78 | /// The delimiter of the CSV can be specified in the registry at the following location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Text. 79 | /// Format can be "TabDelimited", "CSVDelimited" or "Delimited(;)". 80 | /// Or create a schema.ini file in the same folder as the CSV file where you specify the delimiter. 81 | /// 82 | public void Load(string fileName, string sheetName = null) 83 | { 84 | this.FileName = fileName; 85 | this.FileType = GetFileType(); 86 | this.SheetName = sheetName; 87 | 88 | if (!File.Exists(fileName)) 89 | { 90 | throw new FileNotFoundException($"File {fileName} does not exist"); 91 | } 92 | 93 | if (string.IsNullOrEmpty(sheetName)) 94 | { 95 | throw new ArgumentNullException(nameof(sheetName), $"Worksheet name is required for file {fileName}"); 96 | } 97 | 98 | LoadWorksheet(); 99 | } 100 | 101 | private FileType GetFileType() 102 | { 103 | var extension = Path.GetExtension(FileName).ToUpper(); 104 | switch (extension) 105 | { 106 | case ".XLSX": 107 | return FileType.Xlsx; 108 | case ".XLS": 109 | return FileType.Xls; 110 | default: 111 | throw new ArgumentException($"File {FileName} with extension {extension} is not supported"); 112 | } 113 | } 114 | 115 | private string GetConnectionString() 116 | { 117 | switch (FileType) 118 | { 119 | case FileType.Xls: 120 | return $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={FileName};Extended Properties=""Excel 8.0;HDR=YES"""; 121 | default: 122 | return $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={FileName};Extended Properties=""Excel 12.0 Xml;HDR=YES"""; 123 | } 124 | } 125 | 126 | private string GetCommandText() 127 | { 128 | return $"SELECT * FROM [{SheetName}$]"; 129 | } 130 | 131 | private void LoadWorksheet() 132 | { 133 | string connectionString = GetConnectionString(); 134 | 135 | using (var connection = new OleDbConnection(connectionString)) 136 | { 137 | // Get OleDB connection to Excel (XLS/XLSX) or CSV file and open it with a DataReader. 138 | try 139 | { 140 | connection.Open(); 141 | using (var command = connection.CreateCommand()) 142 | { 143 | command.CommandText = GetCommandText(); 144 | using (var reader = command.ExecuteReader()) 145 | { 146 | // Run through fields and create column objects 147 | for (int i = 0; i < reader.FieldCount; i++) 148 | { 149 | Columns.Add(new ExcelColumn(i, reader.GetName(i), reader.GetFieldType(i))); 150 | } 151 | 152 | int rowCount = 1; 153 | // Run through records and create rows with cells with contain the values 154 | while (reader.Read()) 155 | { 156 | var newRow = new ExcelRow(rowCount++, Columns); 157 | for (int index = 0; index < reader.FieldCount; index++) 158 | { 159 | newRow.AddCell(reader[index]); 160 | } 161 | Rows.Add(newRow); 162 | } 163 | } 164 | } 165 | } 166 | finally 167 | { 168 | connection.Close(); 169 | } 170 | } 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/OneNote/OneNoteProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Drawing; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Xml.Linq; 8 | using Microsoft.Office.Interop.OneNote; 9 | using ScipBe.Common.Office.Utils; 10 | 11 | namespace ScipBe.Common.Office.OneNote 12 | { 13 | /// 14 | /// OneNote Provider (LINQ to OneNote). 15 | /// 16 | /// 17 | /// 18 | /// Author: Stefan Cruysberghs 19 | /// Website: http://www.scip.be 20 | /// Article: Querying Outlook and OneNote with LINQ : http://www.scip.be/index.php?Page=ArticlesNET05 21 | /// 22 | /// 23 | public static class OneNoteProvider 24 | { 25 | /// 26 | /// Hierarchy of Notebooks with Sections and Pages. 27 | /// 28 | public static IEnumerable NotebookItems 29 | { 30 | get 31 | { 32 | return CallOneNoteSafely(oneNote => 33 | { 34 | // Get OneNote hierarchy as XML document 35 | oneNote.GetHierarchy(null, HierarchyScope.hsPages, out string oneNoteXMLHierarchy); 36 | var oneNoteHierarchy = XElement.Parse(oneNoteXMLHierarchy); 37 | var one = oneNoteHierarchy.GetNamespaceOfPrefix("one"); 38 | 39 | // Transform XML into object hierarchy 40 | return from n in oneNoteHierarchy.Elements(one + "Notebook") 41 | where n.HasAttributes 42 | select ParseNotebook(n, one, true); 43 | }); 44 | } 45 | } 46 | 47 | /// 48 | /// Collection of Pages. 49 | /// 50 | public static IEnumerable PageItems 51 | { 52 | get 53 | { 54 | return CallOneNoteSafely(oneNote => 55 | { 56 | // Get OneNote hierarchy as XML document 57 | oneNote.GetHierarchy(null, HierarchyScope.hsPages, out string oneNoteXMLHierarchy); 58 | return ParsePages(oneNoteXMLHierarchy); 59 | }); 60 | } 61 | } 62 | 63 | /// 64 | /// Returns a list of pages that match the specified query term. 65 | /// 66 | /// The search string. Pass exactly the same string that you would type into the search box in the OneNote UI. You can use bitwise operators, such as AND and OR, which must be all uppercase. 67 | public static IEnumerable FindPages(string searchString) 68 | { 69 | return CallOneNoteSafely(oneNote => 70 | { 71 | oneNote.FindPages(null, searchString, out string xml); 72 | return ParsePages(xml); 73 | }); 74 | } 75 | 76 | private static IOneNoteExtNotebook ParseNotebook(XElement notebookElement, XNamespace oneNamespace, bool addSections) 77 | { 78 | var notebook = new OneNoteExtNotebook() 79 | { 80 | ID = notebookElement.Attribute("ID").Value, 81 | Name = notebookElement.Attribute("name").Value, 82 | NickName = notebookElement.Attribute("nickname").Value, 83 | Path = notebookElement.Attribute("path").Value, 84 | Color = notebookElement.Attribute("color").Value != "none" ? ColorTranslator.FromHtml(notebookElement.Attribute("color").Value) : (Color?)null, 85 | }; 86 | 87 | if (addSections) 88 | { 89 | notebook.Sections = notebookElement.Descendants(oneNamespace + "Section").Select(s => ParseSection(s, oneNamespace, true)); 90 | } 91 | 92 | return notebook; 93 | } 94 | 95 | private static IOneNoteExtSection ParseSection(XElement sectionElement, XNamespace oneNamespace, bool addPages) 96 | { 97 | var section = new OneNoteExtSection() 98 | { 99 | ID = sectionElement.Attribute("ID").Value, 100 | Name = sectionElement.Attribute("name").Value, 101 | Path = sectionElement.Attribute("path").Value, 102 | Color = sectionElement.Attribute("color").Value != "none" ? ColorTranslator.FromHtml(sectionElement.Attribute("color").Value) : (Color?)null, 103 | Encrypted = (sectionElement.Attribute("encrypted") != null) && (sectionElement.Attribute("encrypted").Value == "true"), 104 | }; 105 | 106 | if (addPages) 107 | { 108 | section.Pages = sectionElement.Elements(oneNamespace + "Page").Select(p => ParsePage(p, oneNamespace, false)); 109 | } 110 | 111 | return section; 112 | } 113 | 114 | private static IOneNoteExtPage ParsePage(XElement pageElement, XNamespace oneNamespace, bool addParents) 115 | { 116 | var page = new OneNoteExtPage() 117 | { 118 | ID = pageElement.Attribute("ID").Value, 119 | Name = pageElement.Attribute("name").Value, 120 | Level = pageElement.Attribute("pageLevel").Value.ToInt32(), 121 | DateTime = pageElement.Attribute("dateTime").Value.ToString().ToDateTime(), 122 | LastModified = pageElement.Attribute("lastModifiedTime").Value.ToString().ToDateTime(), 123 | }; 124 | 125 | if (addParents) 126 | { 127 | var sectionElement = pageElement.Parent; 128 | page.Section = ParseSection(sectionElement, oneNamespace, false); 129 | 130 | var notebookElement = sectionElement.Parent; 131 | while (notebookElement.Name.LocalName == "SectionGroup") 132 | { 133 | notebookElement = notebookElement.Parent; 134 | } 135 | 136 | page.Notebook = ParseNotebook(notebookElement, oneNamespace, false); 137 | } 138 | 139 | return page; 140 | } 141 | 142 | public static IEnumerable ParsePages(string xml) 143 | { 144 | var doc = XElement.Parse(xml); 145 | var one = doc.GetNamespaceOfPrefix("one"); 146 | 147 | var sections = from section in doc.Elements(one + "Notebook").Descendants(one + "Section") 148 | select section; 149 | 150 | // Transform XML into object collection 151 | return from p in sections.Elements() 152 | where p.HasAttributes 153 | && p.Name.LocalName == "Page" 154 | select ParsePage(p, one, true); 155 | } 156 | 157 | internal static T CallOneNoteSafely(Func action) 158 | { 159 | Application oneNote = null; 160 | try 161 | { 162 | oneNote = Util.TryCatchAndRetry( 163 | () => new Application(), 164 | TimeSpan.FromMilliseconds(100), 165 | 3, 166 | ex => Trace.TraceError(ex.Message)); 167 | return action(oneNote); 168 | } 169 | finally 170 | { 171 | if (oneNote != null) 172 | { 173 | Marshal.ReleaseComObject(oneNote); 174 | } 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /Src/ScipBe.Common.Office/Outlook/OutlookProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using Microsoft.Office.Interop.Outlook; 7 | 8 | namespace ScipBe.Common.Office.Outlook 9 | { 10 | /// 11 | /// Outlook Provider (LINQ to Outlook). 12 | /// 13 | /// 14 | /// 15 | /// Author: Stefan Cruysberghs 16 | /// Website: http://www.scip.be 17 | /// Article: Querying Outlook and OneNote with LINQ : http://www.scip.be/index.php?Page=ArticlesNET05 18 | /// Article: Execute queries on Office data with LINQPad : http://www.scip.be/index.php?Page=ArticlesNET06 19 | /// Article: Display Outlook contact pictures in WPF application : http://www.scip.be/index.php?Page=ArticlesNET07 20 | /// Article: Cleaning up Outlook mailboxes : http://www.scip.be/index.php?Page=ArticlesNET27 21 | /// 22 | /// 23 | public class OutlookProvider : IOutlookProvider 24 | { 25 | private readonly Application outlook; 26 | 27 | /// 28 | /// Constructor. Create instance of Office.Interop.Outlook.Application. 29 | /// 30 | public OutlookProvider() 31 | { 32 | outlook = new Application(); 33 | } 34 | 35 | /// 36 | /// Instance of Outlook Application object. 37 | /// 38 | /// 39 | /// 40 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._application_properties.aspx 41 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._application_methods.aspx 42 | /// 43 | /// 44 | public Application Outlook 45 | { 46 | get { return outlook; } 47 | } 48 | 49 | /// 50 | /// Collection of Folder items. 51 | /// The Outlook class holds a hierarchical structure of folders. 52 | /// This property will flatten this hierarchy and return a collection with all folders. 53 | /// 54 | /// 55 | /// 56 | /// http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook._folders_properties.aspx 57 | /// http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook._folders_methods.aspx 58 | /// 59 | /// 60 | public IEnumerable Folders 61 | { 62 | get 63 | { 64 | return GetAllFolders(outlook.GetNamespace("MAPI").Folders.OfType()); 65 | } 66 | } 67 | 68 | private static IEnumerable GetAllFolders(IEnumerable folders) 69 | { 70 | foreach (var folder in folders) 71 | { 72 | foreach (var subfolder in GetAllFolders(folder.Folders.OfType())) 73 | { 74 | yield return subfolder; 75 | } 76 | yield return folder; 77 | } 78 | } 79 | 80 | /// 81 | /// Get Outlook items of a given folder. 82 | /// 83 | /// Type (AppointmentItem, ContactItem, JournalItem, MailItem, NoteItem, PostItem, TaskItem). 84 | /// Outlook folder. 85 | /// Collection of items (AppointmentItems, ContactItems, MailItems, ...). 86 | public IEnumerable GetItems(Folder folder) 87 | { 88 | if (folder == null) 89 | { 90 | throw new ArgumentNullException(nameof(folder), $"Folder is required"); 91 | } 92 | 93 | var type = folder.DefaultItemType.GetItemType(); 94 | if (type.FullName != typeof(T).FullName) 95 | { 96 | throw new ArgumentException($"Folder {folder.FolderPath} does not contain {typeof(T).Name} items"); 97 | } 98 | return folder.Items.OfType(); 99 | } 100 | 101 | /// 102 | /// Get Outlook items of default folder of given type. 103 | /// 104 | /// Type (AppointmentItem, ContactItem, JournalItem, MailItem, NoteItem, PostItem, TaskItem). 105 | /// Default folder of type. 106 | /// Collection of items (AppointmentItems, ContactItems, MailItems, ...). 107 | private IEnumerable GetItems(OlDefaultFolders defaultFolderType) 108 | { 109 | var folder = outlook.GetNamespace("MAPI").GetDefaultFolder(defaultFolderType); 110 | return GetItems(folder.FolderPath); 111 | } 112 | 113 | /// 114 | /// Get Outlook items of a given folder path. 115 | /// 116 | /// Type (AppointmentItem, ContactItem, JournalItem, MailItem, NoteItem, PostItem, TaskItem). 117 | /// Outlook folder path. 118 | /// Collection of items (AppointmentItems, ContactItems, MailItems, ...). 119 | public IEnumerable GetItems(string folderPath) 120 | { 121 | if (folderPath.Substring(0, 2) != @"\\") 122 | { 123 | folderPath = @"\\" + folderPath; 124 | } 125 | 126 | var folder = Folders.FirstOrDefault(f => f.FolderPath == folderPath); 127 | 128 | return GetItems(folder); 129 | } 130 | 131 | /// 132 | /// Collection of Contact Items of default Contacts folder. 133 | /// 134 | /// 135 | /// 136 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._contactitem_properties.aspx 137 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._contactitem_methods.aspx 138 | /// 139 | /// 140 | public IEnumerable ContactItems => GetItems(OlDefaultFolders.olFolderContacts); 141 | 142 | /// 143 | /// Collection of Appointment (Calendar) Items of default Calendar. 144 | /// 145 | /// 146 | /// 147 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._appointmentitem_properties.aspx 148 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._appointmentitem_methods.aspx 149 | /// 150 | /// 151 | public IEnumerable CalendarItems => GetItems(OlDefaultFolders.olFolderCalendar); 152 | 153 | /// 154 | /// Collection of Mail Items of default Inbox folder. 155 | /// 156 | /// 157 | /// 158 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._mailitem_properties.aspx 159 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._mailitem_methods.aspx 160 | /// 161 | /// 162 | public IEnumerable InboxItems => outlook.GetNamespace("MAPI").GetDefaultFolder(OlDefaultFolders.olFolderInbox).Items.OfType(); 163 | 164 | /// 165 | /// Collection of Mail Items of default SendMail folder. 166 | /// 167 | /// 168 | /// 169 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._mailitem_properties.aspx 170 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._mailitem_methods.aspx 171 | /// 172 | /// 173 | public IEnumerable SentMailItems => GetItems(OlDefaultFolders.olFolderSentMail); 174 | 175 | /// 176 | /// Collection of Note Items of default Notes folder. 177 | /// 178 | /// 179 | /// 180 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._noteitem_properties.aspx 181 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._noteitem_methods.aspx 182 | /// 183 | /// 184 | public IEnumerable NoteItems => GetItems(OlDefaultFolders.olFolderNotes); 185 | 186 | /// 187 | /// Collection of Task Items of default Tasks folder. 188 | /// 189 | /// 190 | /// 191 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._taskitem_properties.aspx 192 | /// http://msdn2.microsoft.com/en-us/library/microsoft.office.interop.outlook._taskitem_methods.aspx 193 | /// 194 | /// 195 | public IEnumerable TaskItems => GetItems(OlDefaultFolders.olFolderTasks); 196 | 197 | /// 198 | /// Cleanup contact pictures in Windows temporary folder. 199 | /// 200 | public static void CleanupContactPictures() 201 | { 202 | CleanupContactPictures(Path.GetTempPath()); 203 | } 204 | 205 | /// 206 | /// Cleanup contact pictures in given folder. 207 | /// 208 | /// Path to folder with temporary Outlook contact pictures. 209 | public static void CleanupContactPictures(string path) 210 | { 211 | foreach (string picturePath in Directory.GetFiles(path, "Contact_*.jpg")) 212 | { 213 | try 214 | { 215 | File.Delete(picturePath); 216 | } 217 | catch (IOException ex) 218 | { 219 | Debug.Write(ex.Message); 220 | } 221 | } 222 | } 223 | } 224 | } 225 | --------------------------------------------------------------------------------