- Home
- Forum
- Xamarin.Forms
- save excel file in device and send file as attachment
save excel file in device and send file as attachment
Hi All,
I am new to Xamarin and stuck with something. Please get me an idea how to solve this...
Details:
1. Create and Save a Excel file (I have successfully created one by using ISave and Xamarin.Forms.DependencyService.Get<ISave>().SaveAndView("GettingStared.xlsx", "application/msexcel", stream);
2. I dont get any error message and hence I assume that it has been created in my root directory
3. Then I am trying to either attach that file as an email attachment (UNABLE TO DO SO ???)
4. I have an exercise of converting my data in a ObservableCollection into a CSV file and attached that file into email and successfully sent an email after attaching the same csv file. I have also verified my mailbox and the csv file has been attached successfully in my email mailbox
5. Now, I am trying the same with excel file. I have used XLSIO library of SyncFusion and done the coding but can not attach the excel file
My main objective:
I have a standalone application which allows user to upload an excel file. Once a file is choosen by user, the application successfully reads the data and shows in a form. Then user performs editing the data and after all edit is done, then I want the user to save the data back in somewhere. The only way I did was to send an email by converting my latest data into a csv file and attach that file in email and allow user to send that email. I have attached my gmail account to do so and everything works. But I want to extend my solution by playing with excel. I can successfully read the excel file and load data from 3 sheets. Then user edits the data and my final data is in my observable collection. Then while creating a excel file dynamically and attaching as an attachment, I FAILED. I just want to save the data back to my storage somehow or send a copy in an email attachment.
Any help will be much appreciated pleaseeee.
Kind regards
SIGN IN To post a reply.
15 Replies
1 reply marked as answer
SK
Shamini Kiruba Sobers
Syncfusion Team
July 20, 2020 08:15 AM UTC
Hi Bhabani,
Greetings from Syncfusion.
XlsIO doesn’t have support to attach files as an email attachment. Kindly try Xamarin.Essentials to do so.
You can save the edited Excel file to your storage successfully with the help XlsIO, which is shown in the following UG link. The saved Excel file can be sent as an attachment in a mail using Xamarin.Essentials.
Please let us know if this helps.
Regards,
Shamini
BS
Bhabani Sahoo
July 21, 2020 10:18 PM UTC
Thanks Shamini for the quick answer. Much appreciated.
Can you please answer below?
I want to save the excel file to my local drive in android device and the write permission is also set in manifest file. When i ran below code after setting up all required things, it ran successfully. But i could not physically goto my device storage and spot that file at all. I simply want that the file i saved should be stored in any location so that i can later view the file manually/physically without using the app.
using ISave and Xamarin.Forms.DependencyService.Get<ISave>().SaveAndView("GettingStared.xlsx", "application/msexcel", stream);
Or is it possible that after i prepared the file, the ap should ask me/user where to save the file? That will also solve my problem.
Whichever option works with xlsio library, i just want to save my newly created file to be able to save to the device so that I or the user of the android phone be able to view the physical file later inside the device’s storage somewhere.
Please could you help and guide me in right direction?
Kind regards
KK
Konduru Keerthi Konduru Ravichandra Raju
Syncfusion Team
July 22, 2020 12:21 PM UTC
Hi Bhabani,
Thanks for the update.
This is to inform you that it is not possible to choose the storage location at run-time. The root path in Android device is mentioned in SaveAndroid.cs file as,
Code Snippet:
|
//Get the root path in android device.
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
else
root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); |
But, you can change the Android Environment to your requirement. You need to enable the storage permission for App in your Android Device, to spot the file.
Kindly try this and let us know if the suggestion helps.
Regards,
Keerthi.
BS
Bhabani Sahoo
July 23, 2020 10:28 PM UTC
Hi,
Attachment: Screenshot_20200723_at_23.16.06_26754439.zip
Thanks again. I managed to get deeper this time. (Pls refer the screen capture). I have checked thoroughly that I have granted READ/Write permission in Manifest XML file. But the code still fails because it has not got permission still. I went to device's app management manually to see if my app has permission over storage and yes its all there.
Then I used the plugin (https://forums.xamarin.com/discussion/158119/cant-find-this-folder-on-my-android-emulator) to check if I have permission or not and found that the permission is denied. I wonder what else can I do to enable permission? Am I missing something?
here is the code (it throws exception at FileOutputStream outs = new FileOutputStream(file); saying that no file found. in fact it does not create a folder even if it successfully executed that make directory line and did not throw error):
string root = null;
//Get the root path in android device.
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
else
root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//Create directory and file
Java.IO.File myDir = new Java.IO.File(root + "/Syncfusion12");
myDir.Mkdir();
Java.IO.File file = new Java.IO.File(myDir, fileName);
//Remove if the file exists
if (file.Exists())
file.Delete();
//Write the stream into the file
try
{
FileOutputStream outs = new FileOutputStream(file);
outs.Write(stream.ToArray());
outs.Flush();
outs.Close();
}
catch (Exception ex)
{
string a = ex.Message;
}
Attachment: Screenshot_20200723_at_23.16.06_26754439.zip
KK
Konduru Keerthi Konduru Ravichandra Raju
Syncfusion Team
July 24, 2020 11:37 AM UTC
Hi Bhabani,
Thanks for the update.
This is to inform you that a new runtime permission model is introduced for the Android SDK version 23 and above. So, include the following code for enabling the Android file provider to save and view the generated PDF document.
- Create a new XML file with the name of provider_paths.xml under the Android project Resources folder and add the following code in it.
Eg: Resources/xml/provider_paths.xml
Code Snippet:
|
<?xml version="1.0" encoding="UTF-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths> |
- Add the following code to the AndroidManifest.xml file located under Properties/AndroidManifest.xml.
Code Snippet:
|
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.f156204_xamarin" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:label="F156204_Xamarin.Android">
<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
</provider>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest> |
- You need to enable the storage permission for App in your Android Device, as mentioned in our previous update.
We have created a simple working sample for your reference and the same can be downloaded from the following link.
Sample Link: https://www.syncfusion.com/downloads/support/directtrac/156204/ze/F156204_Xamarin1660950913.zip
Kindly try this and let us know if it helps.
Regards,
Keerthi.
Marked as answer
BS
Bhabani Sahoo
July 24, 2020 03:39 PM UTC
Hi Keerthi,
Attachment: Archive_2ea647cf.zip
I really appreciate your time helping me. Unfortunately, my progress is going like a snail.
1. Thanks for sending the sample link but it doesn't allow me to download/open.
Sample Link: https://www.syncfusion.com/downloads/support/directtrac/156204/ze/F156204_Xamarin1660950913.zip
2. I did exactly what you said and tried. Now, the code successfully creates (I assume) as it doesn't throw error anymore for the step - Java.IO.File file = new Java.IO.File(root1, fileName);. However, I can't view the file by browsing the filesystem of the device.
3. Then I tried to add another step to save to MyDocuments just as a test. Then I went to the MyDocuments folder but still can't see the file. But strangely, when I rerun the app, it goes to the step where it says Delete file if it exists. That indicates (may be) the file has been created but hidden from me viewing. How to make that public instead of private?
4. Attached few screenshots, just for you to understand issues that I am facing
string root = null;
//Get the root path in android device.
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
else
root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string root1 = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//Create directory and file
Java.IO.File myDir = new Java.IO.File(root1 + "/Syncfusion12");
myDir.Mkdir();
//Java.IO.File file = new Java.IO.File(myDir, fileName);
Java.IO.File file = new Java.IO.File(root1, fileName);
//Remove if the file exists
if (file.Exists())
file.Delete();
//Write the stream into the file
try
{
FileOutputStream outs = new FileOutputStream(file);
outs.Write(stream.ToArray());
outs.Flush();
outs.Close();
}
catch (Exception ex)
{
string a = ex.Message;
}
Kind regards,
Bhabani
Attachment: Archive_2ea647cf.zip
KK
Konduru Keerthi Konduru Ravichandra Raju
Syncfusion Team
July 27, 2020 11:21 AM UTC
Hi Bhabani,
Thanks for the update.
We have uploaded the working sample again and you can download it from below.
Sample Link: https://www.syncfusion.com/downloads/support/forum/156204/ze/F156204_Xamarin355141688.zip
Please find the code snippet used in SaveAndroid.cs file below.
Code Snippet:
|
public async Task SaveAndView(string fileName, String contentType, MemoryStream stream)
{
string exception = string.Empty;
string root = null;
//Get the root path in android device.
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
else
root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//Create directory and file
Java.IO.File myDir = new Java.IO.File(root + "/Syncfusion");
myDir.Mkdir();
Java.IO.File file = new Java.IO.File(myDir, fileName);
//Remove if the file exists
if (file.Exists()) file.Delete();
try
{
FileOutputStream outs = new FileOutputStream(file);
outs.Write(stream.ToArray());
outs.Flush();
outs.Close();
}
catch (Exception e)
{
exception = e.ToString();
}
Android.Net.Uri path = Android.Net.Uri.FromFile(file);
string extension = Android.Webkit.MimeTypeMap.GetFileExtensionFromUrl(Android.Net.Uri.FromFile(file).ToString());
string mimeType = Android.Webkit.MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension);
Intent intent = new Intent(Intent.ActionView);
intent.SetFlags(ActivityFlags.ClearTop | ActivityFlags.NewTask);
path = FileProvider.GetUriForFile(Android.App.Application.Context, Android.App.Application.Context.PackageName + ".provider", file);
intent.SetDataAndType(path, mimeType);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
Forms.Context.StartActivity(Intent.CreateChooser(intent, "Choose App"));
} |
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); is a specified system special folder and the folder should physically exist on your computer; otherwise, it returns an empty string (""). Please look into the following link to know more about this.
When storage permission for App is not enabled in your android device,
- myDir.Mkdir(); will be false and the folder Syncfusion will not be created in your device.
- That is when you face the No such file or directory exception.
Kindly try execute the shared sample in your device with storage permissions enabled for the App when it is created, and let us know if the file is saved in the device.
Regards,
Keerthi.
BS
Bhabani Sahoo
July 29, 2020 07:13 AM UTC
Hi,
Thanks a lot for yoir time and patience. I have managed to resolve the problem. The file actually gets created eventhough I cant see it physically. When I tried to share/save the file in device from the same location, it does allow me to save successfully. That means the file is there but just not visible. I am sure it is the simulatir issue or something else but the file is definitely there.
Thank yoi once again for the support. Please close the case.
Kind regards
KK
Konduru Keerthi Konduru Ravichandra Raju
Syncfusion Team
July 29, 2020 07:30 AM UTC
Hi Bhabani,
Thanks for the update. We are glad that you have found a solution.
Regards,
Keerthi.
PV
Pete Vickers
October 5, 2020 01:44 PM UTC
Hi,
I have downloaded the sample and can't get it to work - I am using an Android 9 device.
If I leave the demo as it is then the line
FileOutputStream outs = new FileOutputStream(file);
Fails as 'outs' is null.
If I force it to do
root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
then it succeeds in creating the file but chokes on the line
Intent intent = new Intent(Intent.ActionView);
If it succeeds then I can view it, but get a message saying the file doesn't exist. I need to allow the user to view the file AND email it
Thanks
Pete
KK
Konduru Keerthi Konduru Ravichandra Raju
Syncfusion Team
October 6, 2020 04:46 PM UTC
Hi Pete,
Greeting from Syncfusion.
We are checking your query and will update the details tomorrow (7th October 2020).
Regards,
Keerthi.
KK
Konduru Keerthi Konduru Ravichandra Raju
Syncfusion Team
October 7, 2020 08:36 AM UTC
Hi Pete,
Greeting from Syncfusion.
You need to enable storage permissions for the App your Android device, to overcome the file doesn't exist issue and spot the file. Kindly try this and let us know if this helps.
Regards,
Keerthi.
PV
Pete Vickers
October 7, 2020 08:58 AM UTC
Hi,
this is already set
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Thanks
PV
Pete Vickers
October 7, 2020 01:56 PM UTC
Hi,
I have found another way around it. Instead of trying to launch in the Android save, I just create the file, and then I can use Xamarin.Essentials to launch the program.
That works for me
Thanks
SK
Shamini Kiruba Sobers
Syncfusion Team
October 8, 2020 11:27 AM UTC
Hi Pete,
Thanks for the update. We are glad that you have found a solution.
Regards,
Shamini
SIGN IN To post a reply.
- 15 Replies
- 4 Participants
- Marked answer
-
BS Bhabani Sahoo
- Jul 19, 2020 10:50 PM UTC
- Oct 8, 2020 11:27 AM UTC