convert a shapefile to kml using Gdal library in C# - c#

Hi I want to convert a shapefile (shp) to kml using Gdal library in C#.
I write a code but the output is not in kml format.
Here is my code:
using OSGeo.OGR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSGeo.OSR;
using OSGeo.GDAL;
namespace ConsoleApp1 {
class Program {
static void Main(string[] args) {
GdalConfiguration.ConfigureGdal();
GdalConfiguration.ConfigureOgr();
convert();
}
public static void convert() {
string shapeFilePath = # "C:\riv1.shp";
Ogr.RegisterAll();
var drv = Ogr.GetDriverByName("ESRI Shapefile");
var ds = drv.Open(shapeFilePath, 0);
OSGeo.OGR.Layer layer = ds.GetLayerByIndex(0);
OSGeo.OGR.Feature f;
layer.ResetReading();
System.Text.StringBuilder sb = new System.Text.StringBuilder();
while ((f = layer.GetNextFeature()) != null) {
var geom = f.GetGeometryRef();
if (geom != null) {
var geometryKml = geom.ExportToKML("");
sb.AppendLine(geometryKml);
}
}
var kmlStr = sb.ToString();
System.IO.File.WriteAllText("c:/riv1.kml", kmlStr);
}
}
}
This convert work fine by FWTools Shell but I need to do it in my code.
Please help me if you know what I miss.

You can use the CopyLayer() method to just copy the shapefile layer to a new Kml datasource.
// load the shapefile in a datasoure
Driver shpDriver = Ogr.GetDriverByName("ESRI Shapefile");
DataSource shpDatasource = Ogr.Open(shapefilePath, 0);
if (shpDatasource == null)
return false;
// load the shapefile layer
Layer shpLayer = shpDatasource.GetLayerByIndex(0);
// create the KML datasource layer
Driver kmlDriver = Ogr.GetDriverByName("KML");
DataSource KmlDatasource = Ogr.Open(KmlPath, 0);
KmlDatasource = kmlDriver.CreateDataSource(KmlPath, new string[] {});
// copy the shapefile layer
Layer newLayer = KmlDatasource.CopyLayer(shpLayer, shpLayer.GetName(), new string[] { });

Thank you very much Maxwell77. I just ran it and add tiny modification to let it work correctly.
GdalConfiguration.ConfigureGdal();
GdalConfiguration.ConfigureOgr();
OSGeo.OGR.Ogr.RegisterAll();
Driver drv = Ogr.GetDriverByName("ESRI Shapefile");
DataSource shpDatasource = Ogr.Open(shapefilePath, 0);
if (shpDatasource == null)
return false;
// load the shapefile layer
Layer shpLayer = shpDatasource.GetLayerByIndex(0);
// create the KML datasource layer
using (Driver kmlDriver = Ogr.GetDriverByName("KML"))
{
// DataSource KmlDatasource = Ogr.Open(KmlPath, 0);
using (DataSource KmlDatasource = kmlDriver.CreateDataSource(KmlPath, new string[] { }))
{
// copy the shapefile layer
Layer newLayer = KmlDatasource.CopyLayer(shpLayer, shpLayer.GetName(), new string[] { });
newLayer.Dispose();
}
}
}

Related

Could not load file or assembly 'System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

I am trying to develop a web application that displays some charts based on different data that is stored in a database. I found on different tutorials online that I should transfer the data from the controller to the view using a model and then to use Json.Encode for the data to be read correctly by my chart.
First it didn't recognize Json.Encode method, so I had to use NuGet Packet Manager to install Microsoft.AspNet.WebPages and when I try to run the app, this error pops up.
I am using .NET Core 5.0
This is where the error comes in:
<script type="text/javascript">
var chart = document.getElementById('pie').getContext('2d');
var myChart = new Chart(chart, {
type: 'pie',
data : #Html.Raw(System.Web.Helpers.Json.Encode(Model.PieChartData)),
});
</script>
This is how I build the model that is given to the view:
public PieChartVM GetPieChartData()
{
var model = new PieChartVM();
var labels = new List<string>();
labels.Add("Green");
labels.Add("Blue");
labels.Add("Gray");
labels.Add("Purple");
model.labels = labels;
var dataset = new List<PieChartChildVM>();
var childModel = new PieChartChildVM();
var backgroundColorList = new List<string>();
var dataList = new List<int>();
foreach(var label in labels)
{
if (label == "Green")
{
backgroundColorList.Add("#2ecc71");
dataList.Add(12);
}
if (label == "Blue")
{
backgroundColorList.Add("#3498db");
dataList.Add(20);
}
if (label == "Gray")
{
backgroundColorList.Add("#95a5a6");
dataList.Add(18);
}
if (label == "Purple")
{
backgroundColorList.Add("#9b59b6");
dataList.Add(50);
}
}
childModel.backgroundColor = backgroundColorList;
childModel.data = dataList;
dataset.Add(childModel);
model.datasets = dataset;
return model;
}
Have you tried this:
using System.Text.Json.Serialization;
string jsonString = JsonSerializer.Serialize(yourModel);
OR
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
var jsonModel = serializer.Serialize(YOURMODEL);

PdfLayer.GetTitle() always returning null

C# itext 7.1.4 (NuGet release) doesn't seem to parse OCG/layer titles correctly.
The C# code below should read a pdf, print all layer titles, turn off the layer visibility and save it to the dest file.
Example pdf file: https://docdro.id/qI479di
using iText.Kernel.Pdf;
using System;
namespace PDFSetOCGVisibility
{
class Program
{
static void Main(string[] args)
{
var src = #"layer-example.pdf";
var dest = #"layer-example-out.pdf"; ;
PdfDocument pdf = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
var Catalog = pdf.GetCatalog();
var ocProps = Catalog.GetOCProperties(false);
var layers = ocProps.GetLayers();
foreach(var layer in layers)
{
var title = layer.GetTitle();
Console.WriteLine($"title: {title ?? "null"}");
layer.SetOn(false);
}
pdf.Close();
}
}
}
Expected output is:
title: Layer 1
title: Layer 2
Actual output is:
title: null
title: null
Writing the file with disabled layers works fine but the layer titles are always null.
Just tested the itext5 version:
using iTextSharp.text.pdf;
using System;
using System.IO;
namespace PDFSetOCGVisibility5
{
class Program
{
static void Main(string[] args)
{
var src = #"layer-example.pdf";
var dest = #"layer-example-out.pdf";
var reader = new PdfReader(src);
PdfStamper pdf = new PdfStamper(reader, new FileStream(dest, FileMode.Create));
var layers = pdf.GetPdfLayers();
foreach (var layer in layers)
{
var title = layer.Key;
Console.WriteLine($"title: {title ?? "null"}");
layer.Value.On = false;
}
pdf.Close();
reader.Close();
}
}
}
It's working as expected, so this seems to be a regression in itext7
I don't know what's the purpose of title/GetTitle() but to get the Name (as displayed on the panel) the following code works:
var title = layer.GetPdfObject().GetAsString(PdfName.Name).ToUnicodeString();

Get Outlook Appointments including recurring ones using EWS

I have implemented an SSIS Package getting all appoinments from a particular shared outlook calendar.
What I noticed is that the recurring ones are NOT returned because they are a kind of virtual. Only the Master of them will give me the ability to get also the recurring ones.
Looking at my code, do you have any suggestions how I can retrieve also the recurring ones?
I'm just a little stuck and any hint is highly appreciated!
#region Namespaces
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Microsoft.Exchange.WebServices.Data;
#endregion
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
string sharedCalendarID;
static FolderId FindPublicFolder(ExchangeService myService, FolderId baseFolderId, string folderName)
{
// search using paging.
FolderView folderView = new FolderView(10, 0);
folderView.OffsetBasePoint = OffsetBasePoint.Beginning;
// need only DisplayName and Id of every folder
// reduce the property set to the properties
folderView.PropertySet = new PropertySet(FolderSchema.DisplayName, FolderSchema.Id);
FindFoldersResults folderResults;
do
{
folderResults = myService.FindFolders(baseFolderId, folderView);
foreach (Folder folder in folderResults)
if (String.Compare(folder.DisplayName, folderName, StringComparison.OrdinalIgnoreCase) == 0)
return folder.Id;
if (folderResults.NextPageOffset.HasValue)
// go to the next page
folderView.Offset = folderResults.NextPageOffset.Value;
}
while (folderResults.MoreAvailable);
return null;
}
public override void CreateNewOutputRows()
{
// IMPORTANT: ExchangeService is NOT thread safe, so one should create an instance of
// ExchangeService whenever one needs it.
ExchangeService myService = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
myService.Credentials = new NetworkCredential("username", "password");
myService.Url = new Uri("https://......Exchange.asmx");
// next line is very practical during development phase or for debugging
myService.TraceEnabled = true;
Folder myPublicFoldersRoot = Folder.Bind(myService, WellKnownFolderName.PublicFoldersRoot);
string myPublicFolderPath = #"CHI\WIED PFL Agenda";
string[] folderPath = myPublicFolderPath.Split('\\');
FolderId fId = myPublicFoldersRoot.Id;
foreach (string subFolderName in folderPath)
{
fId = FindPublicFolder(myService, fId, subFolderName);
if (fId == null)
{
// No Calendar found
return;
}
}
// verify
Folder folderFound = Folder.Bind(myService, fId);
if (String.Compare(folderFound.FolderClass, "IPF.Appointment", StringComparison.Ordinal) == 0)
{
sharedCalendarID = fId.ToString(); ;
}
else
return;
CalendarFolder myPublicFolder = CalendarFolder.Bind(myService,
//WellKnownFolderName.Calendar,
fId,
PropertySet.FirstClassProperties);
// search using paging. page size 10
ItemView viewCalendar = new ItemView(10);
// include all properties which we need in the view
// comment the next line then ALL properties will be read from the server.
//viewCalendar.PropertySet = new PropertySet(ItemSchema.Subject, ItemSchema.Id);
viewCalendar.Offset = 0;
viewCalendar.OffsetBasePoint = OffsetBasePoint.Beginning;
viewCalendar.OrderBy.Add(ContactSchema.DateTimeCreated, SortDirection.Descending);
FindItemsResults<Item> findResultsCalendar;
do
{
//SearchFilter searchFilter = new SearchFilter.IsGreaterThan(AppointmentSchema.Start, DateTime.Today);
var searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And,
new SearchFilter.IsEqualTo(ItemSchema.ItemClass, "IPM.Appointment"),
new SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start, DateTime.Now),
new SearchFilter.IsLessThan(AppointmentSchema.Start, DateTime.Now.AddDays(4)));
findResultsCalendar = myPublicFolder.FindItems(searchFilter, viewCalendar);
//get additional properties for each item returned by view, do this as view cannot return a lot of useful stuff like attendees
ServiceResponseCollection<ServiceResponse> addProperties =
myService.LoadPropertiesForItems(from Item item in findResultsCalendar select item,
new PropertySet(
BasePropertySet.IdOnly,
AppointmentSchema.Body,
AppointmentSchema.Subject,
AppointmentSchema.Start,
AppointmentSchema.End,
AppointmentSchema.IsRecurring,
AppointmentSchema.AppointmentType
));
List<Appointment> additionalProperties = new List<Appointment>(addProperties.Count);
if (addProperties != null)
{
foreach (ServiceResponse currentResponce in addProperties)
{
additionalProperties.Add(((Appointment)((GetItemResponse)currentResponce).Item));
}
}
foreach (Item item in findResultsCalendar)
{
Appointment appt = item as Appointment;
if (item is Appointment || appt.AppointmentType == AppointmentType.RecurringMaster)
{
Appointment currentAppointmentAddProps = null;
currentAppointmentAddProps = additionalProperties.Find(
delegate(Appointment arg)
{
return arg.Id == item.Id;
}
);
//convert to int wether the Appointment is recurring or not
int isRecurring = currentAppointmentAddProps.IsRecurring ? 1 : 0;
Appointment appoint = item as Appointment;
OutputRecordSetBuffer.AddRow();
OutputRecordSetBuffer.ActualEndDate = currentAppointmentAddProps.End;
OutputRecordSetBuffer.ActualStartDate = currentAppointmentAddProps.Start;
OutputRecordSetBuffer.Subject = appoint.Subject;
OutputRecordSetBuffer.EntryID = Guid.NewGuid();
//OutputRecordSetBuffer.Detail = appoint.Body.ToString();
//OutputRecordSetBuffer.CalendarID = fId.ToString();
//OutputRecordSetBuffer.AppointmentID = appoint.Id.ToString();
OutputRecordSetBuffer.CalendarID = sharedCalendarID;
OutputRecordSetBuffer.AppointmentID = Guid.NewGuid();
OutputRecordSetBuffer.IsRecurring = isRecurring;
}
}
if (findResultsCalendar.NextPageOffset.HasValue)
// go to the next page
viewCalendar.Offset = findResultsCalendar.NextPageOffset.Value;
}
while (findResultsCalendar.MoreAvailable);
}
}
I have solved my issue on my own :)
Instead of using the ItemView class, I used the CalendarView class.
CalendarView expands also the recurring appointments, thats it :)

Web scraping a listings website

I'm trying to scrape a website - ive accomplished this on other projects but i cant seem to get this right. It could be that ive been up for over 2 days working and maybe i am missing something. Please could someone look over my code? Here it is :
using System;
using System.Collections.Generic;
using HtmlAgilityPack;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using System.Xml.Linq;
using System.IO;
public partial class _Default : System.Web.UI.Page
{
List<string> names = new List<string>();
List<string> address = new List<string>();
List<string> number = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
string url = "http://www.scoot.co.uk/find/" + "cafe" + " " + "-in-uk?page=" + "4";
var Webget = new HtmlWeb();
var doc = Webget.Load(url);
List<List<string>> mainList = new List<List<string>>();
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//h2//a"))
{
names.Add(Regex.Replace(node.ChildNodes[0].InnerHtml, #"\s{2,}", " "));
}
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//p[#class='result-address']"))
{
address.Add(Regex.Replace(node.ChildNodes[0].InnerHtml, #"\s{2,}", " "));
}
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//p[#class='result-number']"))
{
number.Add(Regex.Replace(node.ChildNodes[0].InnerHtml, #"\s{2,}", " "));
}
XDocument doccy = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XComment("Business For Sale"),
new XElement("Data",
from data in mainList
select new XElement("data", new XAttribute("data", "data"),
new XElement("Name : ", names[0]),
new XElement("Add : ", address[0]),
new XElement("Number : ", number[0])
)
)
);
var xml = doccy.ToString();
Response.ContentType = "text/xml"; //Must be 'text/xml'
Response.ContentEncoding = System.Text.Encoding.UTF8; //We'd like UTF-8
doccy.Save(Response.Output); //Save to the text-writer
}
}
The website lists business name, phone number and address and they are all defined by a class name (result-address, result-number etc). I am trying to get XML output so i can get the business name, address and phone number from each listing on page 4 for a presentation tomorrow but i cant get it to work at all!
The results are right in all 3 of the for each loops but they wont output in the xml i get an out of range error.
My first piece of advice would be to keep your CodeBehind as light as possible. If you bloat it up with business logic then the solution will become difficult to maintain. That's off topic, but I recommend looking up SOLID principles.
First, I've created a custom object to work with instead of using Lists of strings which have no way of knowing which address item links up with which name:
public class Listing
{
public string Name { get; set; }
public string Address { get; set; }
public string Number { get; set; }
}
Here is the heart of it, a class that does all the scraping and serializing (I've broken SOLID principles but sometimes you just want it to work right.)
using System.Collections.Generic;
using HtmlAgilityPack;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Linq;
public class TheScraper
{
public List<Listing> DoTheScrape(int pageNumber)
{
List<Listing> result = new List<Listing>();
string url = "http://www.scoot.co.uk/find/" + "cafe" + " " + "-in-uk?page=" + pageNumber;
var Webget = new HtmlWeb();
var doc = Webget.Load(url);
// select top level node, this is the closest we can get to the elements in which all the listings are a child of.
var nodes = doc.DocumentNode.SelectNodes("//*[#id='list']/div/div/div/div");
// loop through each child
if (nodes != null)
{
foreach (var node in nodes)
{
Listing listing = new Listing();
// get each individual listing and manually check for nulls
// listing.Name = node.SelectSingleNode("./div/div/div/div/h2/a")?.InnerText; --easier way to null check if you can use null propagating operator
var nameNode = node.SelectSingleNode("./div/div/div/div/h2/a");
if (nameNode != null) listing.Name = nameNode.InnerText;
var addressNode = node.SelectSingleNode("./div/div/div/div/p[#class='result-address']");
if (addressNode != null) listing.Address = addressNode.InnerText.Trim();
var numberNode = node.SelectSingleNode("./div/div/div/div/p[#class='result-number']/a");
if (numberNode != null) listing.Number = numberNode.Attributes["data-visible-number"].Value;
result.Add(listing);
}
}
// filter out the nulls
result = result.Where(x => x.Name != null && x.Address != null && x.Number != null).ToList();
return result;
}
public string SerializeTheListings(List<Listing> listings)
{
var xmlSerializer = new XmlSerializer(typeof(List<Listing>));
using (var stringWriter = new StringWriter())
using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { Indent = true }))
{
xmlSerializer.Serialize(xmlWriter, listings);
return stringWriter.ToString();
}
}
}
Then your code behind would look something like this, plus references to the scraper class and model class:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TheScraper scraper = new TheScraper();
List<Listing> listings = new List<Listing>();
// quick hack to do a loop 5 times, to get all 5 pages. if this is being run frequently you'd want to automatically identify how many pages or start at page one and find / use link to next page.
for (int i = 0; i < 5; i++)
{
listings = listings.Union(scraper.DoTheScrape(i)).ToList();
}
string xmlListings = scraper.SerializeTheListings(listings);
}
}

Create table using OpenXML in powerpoint

I have a scenario where I have Datagrid in my Silverlight application and I want the data to be exported to Power Point.
I researched and found only links, to export image(screen captured) to powerpoint. In my scenario , a screen capture also wont work as I have scroll bar with 20 columns and it is not getting displayed with the above solution.
Any work around for this scenario.
P.S : I do not intend to use any 3rd party controls.
Edit :
I have now tried to use OpenXML , but i am getting an error as below :
My code is as below :
using A = DocumentFormat.OpenXml.Drawing;
using P14 = DocumentFormat.OpenXml.Office2010.PowerPoint;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using P = DocumentFormat.OpenXml.Presentation;
using D = DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Drawing;
public static void CreateTableInLastSlide(PresentationDocument presentationDocument)
{
// Get the presentation Part of the presentation document
PresentationPart presentationPart = presentationDocument.PresentationPart;
// Get the Slide Id collection of the presentation document
var slideIdList = presentationPart.Presentation.SlideIdList;
if (slideIdList == null)
{
throw new NullReferenceException("The number of slide is empty, please select a ppt with a slide at least again");
}
// Get all Slide Part of the presentation document
var list = slideIdList.ChildElements
.Cast<SlideId>()
.Select(x => presentationPart.GetPartById(x.RelationshipId))
.Cast<SlidePart>();
// Get the last Slide Part of the presentation document
var tableSlidePart = (SlidePart)list.Last();
// Declare and instantiate the graphic Frame of the new slide
P.GraphicFrame graphicFrame = tableSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild(new P.GraphicFrame());
ApplicationNonVisualDrawingPropertiesExtension applicationNonVisualDrawingPropertiesExtension = new ApplicationNonVisualDrawingPropertiesExtension();
P14.ModificationId modificationId1 = new P14.ModificationId() { Val = 3229994563U };
modificationId1.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
applicationNonVisualDrawingPropertiesExtension.Append(modificationId1);
graphicFrame.NonVisualGraphicFrameProperties = new DocumentFormat.OpenXml.Presentation.NonVisualGraphicFrameProperties
(new A.NonVisualDrawingProperties() { Id = 5, Name = "table 1" },
new A.NonVisualGraphicFrameDrawingProperties(new A.GraphicFrameLocks() { NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new ApplicationNonVisualDrawingPropertiesExtensionList(applicationNonVisualDrawingPropertiesExtension)));
graphicFrame.Transform = new Transform(new Offset() { X = 10, Y = 10 });
graphicFrame.Graphic = new A.Graphic(new A.GraphicData(GenerateTable()) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/table" });
presentationPart.Presentation.Save();
}
private static A.Table GenerateTable()
{
string[,] tableSources = new string[,] { { "name", "age" }, { "Tom", "25" } };
// Declare and instantiate table
A.Table table = new A.Table();
// Specify the required table properties for the table
A.TableProperties tableProperties = new A.TableProperties() { FirstRow = true, BandRow = true };
A.TableStyleId tableStyleId = new A.TableStyleId();
tableStyleId.Text = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
tableProperties.Append(tableStyleId);
// Declare and instantiate tablegrid and colums
A.TableGrid tableGrid1 = new A.TableGrid();
A.GridColumn gridColumn1 = new A.GridColumn() { Width = 3048000L };
A.GridColumn gridColumn2 = new A.GridColumn() { Width = 3048000L };
tableGrid1.Append(gridColumn1);
tableGrid1.Append(gridColumn2);
table.Append(tableProperties);
table.Append(tableGrid1);
for (int row = 0; row < tableSources.GetLength(0); row++)
{
// Instantiate the table row
A.TableRow tableRow = new A.TableRow() { Height = 370840L };
for (int column = 0; column < tableSources.GetLength(1); column++)
{
tableRow.Append(CreateTextCell(tableSources.GetValue(row, column).ToString()));
}
table.Append(tableRow);
}
return table;
}
Am i using the correct graphics and transform ??
The line which is causing the problem according to me is :
P.GraphicFrame graphicFrame = tableSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild(new P.GraphicFrame());
As if i comment his line i dont get the error, but neither do i get the table :o/
Any help ?
Finally i was able to solve the problem using the Open XML productivity tool (here) . The line i highlighted was the error. I needed to add the below code :
List<OpenXmlElement> elements = new List<OpenXmlElement>();
elements.Add(new P.NonVisualGraphicFrameProperties
(new P.NonVisualDrawingProperties() { Id = 1, Name = "xyz" }, new P.NonVisualGraphicFrameDrawingProperties(),new ApplicationNonVisualDrawingProperties()));
P.GraphicFrame graphicFrame = tableSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild(new P.GraphicFrame(elements));
Thus i was able to get output without any errors :)

Categories