Get Folder from Outlook using C# & GetFolderFromID EntryIdStore - outlook

I'm trying to get a specific folder in outlook with c#. Someone else had the same issue here Using Outlook API to get to a specific folder but when using the Folders collection I'm not sure how to get through the folders collection. I mean, I've looked at the type of object that the Folders collection returns and it looks like it's a Folders object. But when I try to use that in a loop it gives me an invalid cast exception. I also hoped I could use the GetFolderFromID method to give it the string name of the folder but that doesn't want to work either... but I also can't find an example of how to use it so I'm not sure I'm coding it correctly. Here's an example of what I tried. Anyone know how to get the Processed folder which is on the same level as the Inbox folder? Thanks.
MAPIFolder oProcessed = null;
foreach (var folder in oNS.Folders)
if (folder.ToString() == "Processed")
{
oProcessed = (MAPIFolder)folder;
}
if (oProcessed == null)
throw new Exception("Missing processed folder.");

you need to get hold of the root level mailbox folder
Outlook.MAPIFolder rootFolder= Application.Session.DefaultStore.GetRootFolder();
Then loop through the rootFolder folders collection check in the names
Outlook.MAPIFolder processedFolder = null;
foreach (Outlook.MAPIFolder folder in rootFolder.Folders)
{
if (folder.Name == "Processed")
{
processedFolder = folder;
break;
}
}
Check out http://msdn.microsoft.com/en-us/library/bb176810.aspx to get you head round the API.
Marcus

Outlook.MAPIFolder rootFolder = Application.Session.DefaultStore.GetRootFolder();
var processedFolder = rootFolder.Folders.Cast<Outlook.MAPIFolder>().Where(r => r.Name == "Processed").FirstOrDefault();

This is an inept translation from VBA, but may offer some ideas, seeing you have no answers as yet. In VBA, it is best to get the parent folder of Inbox and to look in that for folders at the same level.
Microsoft.Office.Interop.Outlook._Folders oFolders;
Microsoft.Office.Interop.Outlook.MAPIFolder oPublicFolder =
olNS.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox).Parent;
//Folders at Inbox level
oFolders = oPublicFolder.Folders;
foreach (Microsoft.Office.Interop.Outlook.MAPIFolder Folder in oFolders)
{
string foldername = Folder.Name;
if (foldername == "Test")
Console.Write(Folder.Name);
}

If you have the folder path as a string, you can use this function:
private MAPIFolder GetFolder(string folderPath, Folders folders)
{
string dir = folderPath.Substring(0, folderPath.Substring(4).IndexOf("\\") + 4);
try
{
foreach (MAPIFolder mf in folders)
{
if (!(mf.FullFolderPath.StartsWith(dir))) continue;
if (mf.FullFolderPath == folderPath) return mf;
else
{
MAPIFolder temp = GetFolder(folderPath, mf.Folders);
if (temp != null)
return temp;
}
}
return null;
}
catch { return null; }
}

Related

Google Team Drive : List changes not giving any result if requested for particular team drive

I tried using change id "1" too. But it returns empty result.
However if searched for the whole drive (team drives and My drive) , it is working fine.
I tried this on google API sandbox. Gives the same result.
Here is the code snippet i used.
List<Change> allteamdriveChanges = new List<Change>();
ChangesResource.ListRequest req = _gdrive.Changes.List();
req.StartChangeId = (long)(Convert.ToUInt64(changeId) + 1);
req.MaxResults = 1000;
req.IncludeTeamDriveItems = true;
req.SupportsTeamDrives = true;
req.TeamDriveId = teamDriveId;
do
{
ChangeList changes = req.Execute();
foreach(var change in changes.Items)
{
allteamdriveChanges.Add(change);
}
currentChangeId = changes.LargestChangeId.ToString();
req.PageToken = changes.NextPageToken;
} while (!String.IsNullOrEmpty(req.PageToken));
return allteamdriveChanges;
Can anyone look into this ?

Get the row count of an XLSX file

I want to create a list of all the .xlsx files on my computer and the number of rows in them.
What is the best way to get the # of rows in each .xlsx file? I'm on Mac OSX Yosemite (if it's relevant). The answer can be in any language.
You can do it with PHP and Spout (https://github.com/box/spout).
The code would look something like this:
use Box\Spout\Reader\ReaderFactory;
use Box\Spout\Common\Type;
// This is the root directory you want to list the XLSX files of
// CHANGE IT !!
$rootPath = '/path/to/root/directory';
// this will read the XLSX file at the given path and return the number of rows for the file
function getNumRows($xlsxPath) {
$numRows = 0;
$reader = ReaderFactory::create(Type::XLSX);
$reader->open($xlsxPath);
foreach ($reader->getSheetIterator() as $sheet) {
foreach ($sheet->getRowIterator() as $row) {
$numRows++;
}
}
$reader->close();
return $numRows;
}
// This will recursively go through the root folder and all its subfolders
$directoryIterator = new \RecursiveDirectoryIterator($rootPath, RecursiveDirectoryIterator::SKIP_DOTS);
$recursiveIterator = new \RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($recursiveIterator as $fileInfo) {
if (strtolower($fileInfo->getExtension()) === 'xlsx') {
$xlsxPath = $fileInfo->getPathname();
$numRows = getNumRows($xlsxPath);
// store the number of rows for the file somewhere
}
}

How to get sub-folder names from a given path Server.MapPath

I want get the folder names from server.MapPath in ASP.NET MVC 3 application.
In this action, I have to check (if there exist more folders in a given folder name) if a .jpg file is in that folder and if so, return that folder.
string path = Server.MapPath("Content/");
DirectoryInfo dInfo = new DirectoryInfo(path);
DirectoryInfo[] subdirs = dInfo.GetDirectories();
if (Directory.Exists(path))
{
ArrayList ar = new ArrayList();
// This path is a directory
ar.Add(path);
//ProcessDirectory(path);
}
I'm not sure I've understand the qestion correctly, but I think you want something like
string path = Server.MapPath(YOURPATH);
List<string> files = Directory.GetFiles(path, "*.jpg", SearchOption.AllDirectories);
or something like
string path = Server.MapPath(YOURPATH);
List<string> picFolders = new List<string>();
if(Directory.GetFiles(path, "*.jpg").Length > 0)
picFolders.Add(path)
foreach(string dir in Directory.GetDirectories(path, "*", SearchOption.AllDirectories))
{
if(Directory.GetFiles(dir, "*.jpg").Length > 0)
picFolders.Add(dir)
}

check if a sheet exists in excel

How do i check if a sheet exists in a excel using interop. I tried the following but it throws an COMException if not there.. Is there a better way of finding out than actually looking at the exception
Worksheet sheet = null;
Sheets worksheets = some;
sheet = (Worksheet)worksheets.get_Item("sheetName");
if(sheet!=null)
{
//do something
}
Edit:
Thanks for the input guys.
i wrote a function
private Dictionary<string, Worksheet> GetSheetsMap(Sheets worksheets)
{
if (worksheets == null)
throw new ArgumentNullException("worksheets");
Dictionary<string, Worksheet> map = new Dictionary<string, Worksheet>(StringComparer.CurrentCultureIgnoreCase);
foreach (Worksheet s in worksheets)
{
map.Add(s.Name, s);
}
return map;
}
And i use it as below
Dictionary<string, Worksheet> sheetMap = GetSheetsMap(worksheets);
Worksheet sheet = null;
if (sheetMap.TryGetValue(ExtendedTemplateManager.BasicUserTemplate, out sheet))
{
//found it.
}
else
{
// not
}
Do you have a Workbook object? If so, you can iterate over the Workbook.Sheets array and check the Name property of each Sheet.
foreach (Sheet sheet in workbook.Sheets)
{
if (sheet.Name.equals("sheetName"))
{
//do something
}
}
First consider if an exception isn't actually appropriate. You expect a sheet with a certain name to be there. If it isn't, can you still meaningful continue running your program?
If you can, you can avoid the exception by iterating the sheets collection and look for a match on the Name property.
Here's a LINQ way to do it (and this method returns null if the sheet doesn't exist):
workbook.Worksheets.Cast<Worksheet>().FirstOrDefault(worksheet => worksheet.Name == worksheetName);
If you have worksheet and workbook objects them you can do parent check
if (sheet.Parent == workbook)

How do I read the Received Date from Outlook MSG files -without- the Outlook API?

I need to read stuff from an Outlook msg file. Currently I'm using a class from CodeProject.com project to accomplish this, since deploying VSTO and Outlook on a server is not an option.
This class gets To, From, CC, Subject, Body, and everything else I need from the msg file, except Date information (such as Received Date and Sent Date).
There is some (really, really low-level) documentation on how to get stuff out of msg files on MSDN, but it's a little beyond the scope of this project and doesn't mention dates at all.
Ideally I'd be able to have a drop-in replacement for the class I am using now (OutlookStorage.cs in the previously mentioned CodeProject) or be able to modify the existing class a bit. To modify, I would need the correct 4 character hexidecimal prop identifier for received date. For instance, Subject is listed as PR_SUBJECT = "0037" and Body is listed as PR_BOY = "1000".
If you're using OutlookStorage.cs from CodeProject, then add the following:
private const string PR_RECEIVED_DATE="007D";
private const string PR_RECEIVED_DATE_2 = "0047";
...
/// <summary>
/// Gets the date the message was received.
/// </summary>
public DateTime ReceivedDate
{
get
{
if (_dateRevieved == DateTime.MinValue)
{
string dateMess = this.GetMapiPropertyString(OutlookStorage.PR_RECEIVED_DATE);
if (String.IsNullOrEmpty(dateMess))
{
dateMess = this.GetMapiPropertyString(OutlookStorage.PR_RECEIVED_DATE_2);
}
_dateRevieved = ExtractDate(dateMess);
}
return _dateRevieved;
//return ExtractDate(dateMess);
}
}
private DateTime _dateRevieved = DateTime.MinValue;
private DateTime ExtractDate(string dateMess)
{
string matchStr = "Date:";
string[] lines = dateMess.Split(new String[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
if (line.StartsWith(matchStr))
{
string dateStr = line.Substring(matchStr.Length);
DateTime response;
if (DateTime.TryParse(dateStr, out response))
{
return response;
}
}
}
return DateTime.MinValue;
}
I think the Aspose library will do what you want, ok it a 3rd party lib so may not be what you want. There are a few vbs scripts around that get basic infomation out of msg files that could be translated.
Got a hint from this:
string fullFileName = "c:\message.msg";
DateTime dateRevieved = new DateTime();
StreamReader sr = new StreamReader(fullFileName, Encoding.Default);
string full = sr.ReadToEnd();
string date;
int iStart;
int iLast;
string caption;
//This -should- handle all manner of screwage
//The ONLY way it would not is if someone guessed the -exact- to-the-second
//time that they send the message, put it in their subject in the right format
while (true) { //not an infinite loop, I swear!
caption = "Date:";
if (full.IndexOf("Date:") > -1) { //full shortens with each date is removed
string temp = "";
iStart = full.LastIndexOf(caption);
temp = full.Remove(0, iStart + caption.Length);
full = full.Substring(0, iStart);
iLast = temp.IndexOf("\r\n");
if (iLast < 0) {
date = temp;
} else {
date = temp.Substring(0, iLast);
}
date = date.Trim();
if (date.Contains(subject) || subject.Contains(date)) {
continue; //would only happen if someone is trying to screw me
}
try {
dateRevieved = DateTime.Parse(date); //will fail if not a date
break; //if not a date breaks out of while loop
} catch {
continue; //try with a smaller subset of the msg
}
} else {
break;
}
}
This is kind of a hack compared to the ways you can get other things from msg files using something this lovely project. Still, it's stood up to everything I have thrown against it, and as noted the -only- way to fool it is to put the exact to-the-second date in the subject line in the proper format.
to combine your two posts I would suggest the following solution:
To modify, I would need the correct 4 character hexidecimal prop identifier for recieved date. For instance, Subject is listed as PR_SUBJECT = "0037" and Body is listed as PR_BOY = "1000".
Look for "007D".
Use the method you posted in your second post on the received data to eliminate the problem when the same (date) string is inside the subject.
I have to mention that this method doesn't seem to work on internal eMails: In mails I receive from colleagues, there is no substg1.0_007Dxxxx-Property.
Here, the date seems to be hidden in substg1.0_0047xxxx.
All the best!
inno

Resources