I'm using Aspose.HTML for .NET version 19.2 to render an HTML document as an image, using this example as a starting point.
The document I need to convert to an image is an organisational structure diagram, created by the Google Visualization API, which is rendered as a table. This table is the only element in the body of the HTML document, and there are no nested tables.
Due to different organisations having wildly differing structures, the table can vary in size from one or two row/columns up to 20 or so rows and several hundred columns.
What I would like to do is make an image of the entire table, which I can then scale to include in a PDF.
I've written a console app to test this, using the following c# code:
private const string Directory = "C:\\Temp\\Aspose";
static void Main(string[] args)
{
GenerateImage("SimpleTable.html");
GenerateImage("ComplexTable.html");
}
private static void GenerateImage(string htmlFilename)
{
using (var imageMemoryStream = new MemoryStream())
using (var imageDevice = new ImageDevice(new ImageRenderingOptions(), imageMemoryStream))
using (var htmlRenderer = new HtmlRenderer())
using (var htmlDocument = new HTMLDocument(Path.Combine(Directory, htmlFilename)))
{
htmlRenderer.Render(imageDevice, htmlDocument);
var image = Image.FromStream(imageMemoryStream);
image.Save(Path.Combine(Directory, $"Structure{DateTime.Now:yyyyMMddHHmmssfff}.png"), ImageFormat.Png);
}
}
I have three problems:
The image seems to be rendered from an imaginary viewport. The image of the simple table is much bigger than it needs to be and has small table at the top of the image with the rest of the image empty, while the image of the complex table has exactly the same dimensions but contains a slice of the table with the rest of it cut off. Is it possible to change this so that the image is sized appropriately for the page being rendered?
The text in the cells of the complex table spills out beyond the cells.
The CSS for rounded borders seems to be completely ignored.
I've created a zip file containing sample html for a simple and complex table.
The images look like this:
Related
Say I have multiple images in a folder in Assets and I would like to put them in a ForEach loop. And there are too many to manually type the image names into an array. Is there a way to generate such an array with code?
ForeEach(1…30) { item in
Image (“Folder\(image name)”)
}
Big TIA from a newbie
I wanted to know if there's a way to have a parameter that holds an image.
The problem: I have 10 PBIX, each one containing over 20 screens. every report has the clients logo. it is an image let's say the client changed his logo, that means I'll need to change the logo 200 times!! (10 PBIX X 20 screens).
Wanted solution: is there a way to hold a parameter that will contain the logo, therefore changing the logo only 10 times (for each PBIX) that will be a HUGE improvement for my time and productivity. sorry for not including pictures this is to keep my client anonymous
Thank you!
Here is how you can achieve your requirement as stated below-
Step-1 create a custom function in Power Query as stated below. The function is taken from Here and you can check this blog for more details if you are interested.
let
BinaryToImage = (BinaryContent as binary) as text =>
let
Base64 = "data:image/jpeg;base64, " & Binary.ToText(BinaryContent, BinaryEncoding.Base64)
in
Base64
in
BinaryToImage
Here below is the image for the custom function-
Step-2 create report wise folder in your local directory and keep your image there. I am considering one folder here, but you can do your own once you get the workaround.
Step-3 Create a data connection for Folder as shown below and point to the folder you kept your logo/image-
And now you will have a table as below with one row as there are one image only. I named the table as PBI_Images.
Here basically Content column holding the Binary data for the image and we have to convert it to Base64 using the Function we created earlier.
Step-4 Now lets Invoke the function in our table. Select the table and do what shown in the below image-
Now you have a new column with data like below-
Step-5 Get back to report by clicking "Close & Apply" button.
Step-6 Download the following App from AppStore-
Step-7 Just add the new downloaded visual to your report and put the newly created column to the "Image URL" field as below-
Step-8 Now add the Image visual to all your report pages and tag the Image URL as stated in step-7.
You are all done now. Just Change the Image in your source file keeping the same name and after that refresh your table (PBI_Images my case) and you will see Image changes everywhere in the report.
Finally, if everything works expected, you can first try will all logos from one single folder. If do not work, go for folder per customer as mentioned earlier.
can anyone help me? I would like to show Custom Image (the images uploaded in static file ) in the List. I've already tried it in the by (shared components/list/(Image/Class) /#APP_IMAGES#ad.png)
but that not working fine , how i can do that in below list or how i can add new icon in icon file ?
please any advise .
The following steps were tested on APEX 19.2.
Resize your image to 16px square. The CSS used to add the image will not allow the image to be resized via CSS, so this needs to be done ahead of time. You could choose a different image size, but that would require adjusting other aspects of the menu. See the notes at the bottom about this if needed.
Upload the image to the Shared Components and get the URL from the Reference column in the report. You can use either Static Application Files or Static Workspace Files depending on your needs. I used Static Application Files and the URL was: #APP_IMAGES#dm-16.jpg
Go to Shared Components > Lists. Select the list you'd like to work with and then drill down into the list entry where you'd like to display the image. In the Image/Class field, add a custom class that you can use to target the element. I used: dm-16
Go to the page where you have the button setup to open the menu. If you don't already have this setup, you can use this as a guide. Go into the page-level attributes and add the following CSS to the Inline filed in the CSS section:
.dm-16:before {
content: url(#APP_IMAGES#dm-16.jpg);
}
The CSS is selecting the class from step 3 and setting the content attribute using the value from step 2.
When you run the page you should see something like this:
Here are some notes about using larger images... There's a span that wraps the span with the image and has a class named a-Menu-statusCol. That element has its width attribute set to 32px. This is because its left and right padding are set to 8px each (16px total) so when you add the image at 16px the total width becomes 32px.
Let's say you want to use an image that's 32px wide. You'd need to take the padding (16px) and add the width of the image (32px) and set the span's width to that total. In my example that was 48px. I added the following CSS to the same inline attribute in the page:
.a-Menu-content .a-Menu-statusCol {
width: 48px
}
After that, you'll see that the image doesn't align correctly with the text anymore. This is because the text is in an 'a' element that has its line-height set according to the previous image size. Again, the height is being driven by the span with a class named a-Menu-statusCol. It has top and bottom padding of 10px each (20px total). If you add the default image height (16px) the total comes to 36px, which is what the line-height of the 'a' element is set to. If you add an image with a height of 32px, you'll need to add 20px to that to get a total of 52px. I set the 'a' elements light-height to that value with the following CSS on the same page:
.a-Menu .a-Menu-item {
line-height: 52px;
}
As you can see, the image is now bigger. It doesn't line up with the icon below it as I've not added a larger image to that list entry.
Using DotSpatial, if I open a Shapefile as an IFeatureSet, I can see a collection of shapes within the FeatureSet and these shapes have collections of attributes. But I can't see an obvious way of finding the name associated to the shape?
For example, if I have the following code:
var featureSet = Shapefile.Open("../../Ecuador/map.shp");
var rowCount = featureSet.NumRows();
for (var i = 0; i < rowCount; i++)
{
var shape = featureSet.GetShape(i, true);
var geometry = shape.ToGeometry();
}
If I debug into this code by putting a breakpoint on the Shape object I can see a collections of attributes. In the example I'm using, each shape has 12 attributes. I can see that one of these attributes is what I would consider to be the name of the shape (in this example I'm looking at the provinces of Ecuador), but I have no idea how to reliably pair which one of these attributes would be the shape name, in this case the name of the province.
Edit
Here is an example of the available attributes I can see for the first shape:
From a quick look, I'd say that the attribute at index 4 was the one I need, but how do I find this out programmatically?
Further Edit
It looks as though, through further poking about in the data that the labels for the attributes might be the DataTable Column names in the IFeatureSet:
Although... which of these would I pick programmatically if I wanted to import these shapes? Is the only way to allow the person doing the import to manually pick the correct one?
I found a page called Importing Geographic Information Systems (GIS) data in Google Earth.
The process to import from a shapefile shows a screenshot where the user is asked to select the attribute that contains the names for the shapes, from a table of available attributes.
It looks as though the task of attaching names to features is handled manually by the user.
I am trying to figure out how to calculate, then store the layout delta for a rendering programatically. The situation I'm in is that I have a rendering defined on my standard value. It's datasource is empty. I then have a process that creates an item based on that template, but I need to set the datasource on the rendering.
By default, the __Renderings field on the new item is blank (as is expected). So far, I've been able to get a RenderingReference to my rendering, detect that the datasource is blank, but I cannot for the life of me figure out how to set the datasource then store the correct delta in the __Renderings field on my item.
So far I have:
foreach (var device in new DeviceRecords(database).GetAll())
{
foreach (var rendering in myItem.Visualization.GetRenderings(device, false).Where(r => r.RenderingID == renderingId)
{
if (rendering.Settings.DataSource.IsNullOrEmpty())
{
var dataSourceItem = datasourceFolder.Add("Datasource name", dataSourceTemplate);
rendering.Settings.DataSource = dataSourceItem.ID.ToString();
using (new EditingContext(myItem)){
myItem[FieldIDs.LayoutField] == //????
}
}
}
}
My guess is I need to somehow invoke something in XmlDelta, but it looks like all of those methods want some Xml to work with, when all I have is the rendering item.
I wrote some code a while back that tried to extract data source information from Sitecore's XML deltas. I never tried updating it though, but this may work for you.
The class I used was Sitecore.Layouts.LayoutDefinition which is able to parse the XML and if I remember correctly it deals with the business of working out what the correct set of page controls is by combining the delta with the underlying template data. You can construct it like so:
string xml = LayoutField.GetFieldValue(item.Fields["__Renderings"]);
LayoutDefinition ld = LayoutDefinition.Parse(xml);
DeviceDefinition deviceDef = ld.GetDevice(deviceID);
foreach(RenderingDefinition renderingDef in deviceDef.GetRenderings(renderingID))
{
// do stuff with renderingDef.Datasource
}
So I think you can then use the API that LayoutDefinition, DeviceDefinition and RenderingDefinition provides to access the data. There's a bit more info on how I used this in the processImages() function in this blog post: https://jermdavis.wordpress.com/2014/05/19/custom-sitemap-filespart-three/
I think the missing step you're after is that you can modify the data this object stores (eg to set a data source for a particular rendering) and then use the ToXml() method to get back the revised data to store into your Renderings field?
You may be able to find more information by using something like Reflector or DotPeek to look inside the code for how something like the Layout Details dialog box modifies this data in the Sitecore UI.
-- Edited to add --
I did a bit more digging on this topic as I was interested in how to save the data again correctly. I wrote up what I discovered here: https://jermdavis.wordpress.com/2015/07/20/editing-layout-details/