Exploring the FlexGrid Export Feature
We've added a new exporting feature to the Xamarin FlexGrid for 2019 v1 which helps users preserve their data in several different file formats. This new feature allows you to save a file to device or stream easily. Files can be exported to CSV, text, and HTML files with different options for encoding and presentation of the FlexGrid data using the Save() method. Files can be saved to either the file system, a Stream, or a StreamWriter.
Read the full ComponentOne 2019 v1 release.
Exporting Data
We've included an export sample into FlexGrid101 that illustrates how the export feature works, but you can save a file to the file system of a device quite easily:
string PathAndName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), “MyFile.csv”);
grid.Save(PathAndName, GridFileFormat.Csv, System.Text.Encoding.UTF8, GridSaveOptions.None);
CSV and text files both are unformatted, but the HTML export will reflect cell merging, grid lines, padding, and color changes.
There are many different overloads for the Save method depending on whether you need to save to a stream or the file system:
Overload | Description |
---|---|
Save(StreamWriter, GridFileFormat, GridSaveOptions) | Saves the contents of the grod to a System.IO.StreamWriter |
Save(Stream, GridFileFormat,Encoding,GridSaveOptions) | Saves the contents of the grod to a stream |
Save(Stream, GridFormat, GridSaveOptions) | Saves the contents of the grid to a UTF8 encoded stream |
Save(Stream, GridFileFormat) | Saves the contents of the grid to a UTF8 encoded stream |
Save(String, GridFileFormat, Encoding, GridSaveOptions) | Saves the contents of the grid to a file with a given name |
Save(String, GridFileFormat, GridSaveOptions) | Saves the contents of the grid to a UTF8 encoded file |
Save(String, GridFileFormat) | Saves the content of the grid to a UTF8 encoded file |
You can also use the FileFormat Enumeration to save the file in different formats.
Member | Description |
---|---|
CSV | Commas separated values |
HTML | Hypertext markup language |
Text | Tab separated plain text |
The System.Text.Encoding is also a system that dictates what encoding format you use when saving data. The default is UTF8.
The GridSaveOptions Enumeration allows you to control how your data is saved. You can choose to save formatted values, save only visible data (whether columns or rows), and also whether to save headers.
Member | Description |
---|---|
Formatted | Save formatted values |
None | No options set |
SaveColumnHeaders | Save column headers |
SaveHeaders | Save column and row headers |
SaveRowHeaders | Save row headers |
VisibleColumns | Save only visible columns |
VisibleOnly | Save only visible rows and columns |
VisibleRows | Save only visible rows |
Permissions
Another important aspect when interacting with mobile file systems is that you follow the appropriate rules and add the write permissions to interact with a local file. In the code sample we've given above for saving, there aren't any special permissions needed for file access. However, if you choose another file location each platform will have different rules.
If you want to provide user accessible files on iOS, Apple has added a Files application to iOS 11. It allows you to open local files on a device, but you need to add some keys to you Info.plist for those files to be discoverable. All you need to do is add the following:
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
You should now be able to discover and open any files you’ve saved to the device using Apple’s Files app:
On Android, you'll need to add a permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Saving a file to External Storage allows the user to access the file outside of your app. If you'd prefer to constrain access so that it's only to your app you can limit it to Internal Storage instead.
UWP has many different permissions for different folders, so what you'll need to add will vary depending what you’re trying to access. You'll need to add the permission that you want to use the Package.appxmanifest. You can refer to this reference to find the various permissions you'll need for each folder: https://docs.microsoft.com/en-us/windows/uwp/files/file-access-permissions
UWP also has a broader set of permissions you can use for accessing the file system that is less granular:
xmlns:rescap=http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="broadFileSystemAccess" />
</Capabilities>
File Access by Device
You may find that you want a different file location on each platform since each has their own conventions, and in that case you may want to write your own dependency service. A dependency service allows you to create an interface which than has different implementations on each platform. We've documented how this can be done in the past, but we'll highlight a quick example here.
First, you'll need to create an interface within your .NET Standard project. The IFileSystem interface will be relatively simple, and it will have an implementation inside each platform project:
namespace FlexGrid101
{
public interface IFileSystem
{
string GetFileSystemPath (string FileName, string type);
}
}
On Android, you'll likely want to save into external storage (since it's user accessible), so you'll want to implement the following:
[assembly: Xamarin.Forms.Dependency(typeof(FlexGrid101.Android.FileSystem))]
namespace FlexGrid101.Android
{
public class FileSystem : IFileSystem
{
public string GetFileSystemPath (string FileName, string type)
{
string PathAndName = Path.Combine(Environment.ExternalStorageDirectory.Path, FileName) + "." + type;
return PathAndName;
}
}
}
Note that the Environment object in the above code refers to Android.OS.Environment.
In iOS, we can save it within the documents directory:
[assembly: Xamarin.Forms.Dependency(typeof(FlexGrid101.iOS.FileSystem))]
namespace FlexGrid101.iOS
{
public class FileSystem : IFileSystem
{
public string GetFileSystemPath (string FileName, string type)
{
string PathAndName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), FileName) + "." + type;
return PathAndName;
}
}
}
Note that this Environment is System.Environment.
On UWP we can save it to a similar directory as on iOS:
[assembly: Xamarin.Forms.Dependency(typeof(FlexGrid101.UWP.FileSystem))]
namespace FlexGrid101.UWP
{
public class FileSystem : IFileSystem
{
public string GetFileSystemPath (string FileName, string type)
{
string PathAndName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), FileName) + "." + type;
return PathAndName;
}
}
}
Now that the implementations are finished, we can call the dependency service using the following code within the .NET Standard project:
var fileSystem = DependencyService.Get<IFileSystem>();
string PathAndName = fileSystem.GetFileSystemPath(FILENAME, type);
You can further tweak this pattern to suite your needs.
Please leave us your thoughts in the comments below, and happy coding!