Converting HTML to PDF Invoice - c#

I'm trying to generate HTML page ( C# Razor View ) that will be converted to PDF ( using wkhtmltopdf )and printed on pre-printed stationery.
My problems is, that the pre-printed stationery has a header ( easy )
and tear-off part at the bottom (4cm) which should be blank until the very last page where some additional information is printed.
The whole invoice is being generated as
<table><thead></thead><tbody></tbody></table>
So how can I set margin of X on every page except the last printed
and on that last printed page instead of margin actually print something?
Tried to use with last-child selector but that did not work.
Perhaps some other solution will be more suitable for this using .Net Core ( some linux apps can be used as well )?

You can use the CSS #page rule to specify the page margins. You can also use this to specify additional margins for left & right-hand pages (to account for binding) and for the first page but not, it would seem, for the last page!
/* Default left & right is 2cm, top & bottom margin is 4cm */
#page { margin: 4cm 2cm }
/* First page, 10 cm margin on top */
#page :first {
margin-top: 10cm;
}
/* Left pages, a wider margin on the left */
#page :left {
margin-left: 3cm;
margin-right: 2cm;
}
/* Right pages, a wider margin on the right */
#page :right {
margin-left: 2cm;
margin-right: 3cm;
}
Further reading: https://www.w3.org/TR/CSS21/page.html#page-box

Finally I got to the bottom of that.
As the top of the page should not be a problem ( can be handled the same way as well , but the table thead is another option )
My solution is:
wkhtmltopdf test.html --footer-html footer.html output.pdf
And the whole trick is withing the footer.html file:
<!DOCTYPE html>
<html>
<head>
<script>
var mainHeader = "test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>";
var secondHeader = "OOOOOOOOOOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPOPPOPO<br>";
function selectHeader() {
var vars = {};
var x = document.location.search.substring(1).split('&');
for (var i in x) {
var z = x[i].split('=', 2);
vars[z[0]] = decodeURIComponent(z[1]);
}
if (vars["page"] == vars['topage']) {
document.getElementById('main').innerHTML = secondHeader;
} else {
document.getElementById('main').innerHTML = mainHeader;
}
if (vars["page"] == vars['frompage']) {
document.getElementById('test').innerHTML = secondHeader;
}
}
</script>
</head>
<body onload="selectHeader()">
<div style="min-height: 6cm; background-color: aqua; max-height: 6cm; overflow:visible;">
<div id="main" onload="selectHeader()">
</div>
</div>
</body>
</html>
ps.
Read somewhere that without !DOCTYPE html it might not work.
Thanks for all the help

Related

Execute F11 keypress programmatically on view load for MVC 5 website

We are developing a website using MVC 5. We would like to automatically simulate a keypress (F11) when one of the views loads. This must happen automatically on view load.
The whole purpose of this is to make the browser fullscreen.
So far we have the following code bellow which works when testing locally but when we release it live to Azure, it does not work.
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
[STAThread]
public ActionResult StudentView()
{
while (true)
{
Process[] processes = Process.GetProcessesByName("chrome");
foreach (Process proc in processes)
{
SetForegroundWindow(proc.MainWindowHandle);
SendKeys.SendWait("{F11}");
}
Thread.Sleep(5000);
return View();
}
}
We have also tried some of the solutions in this question but again it does not work when the website is released to live. Simulating Key Press c#
Please assist us to make the browser full screen when view loads. Thanks in advance.
I am afraid you'll need a different approach. Not all browsers will use F11 to go full screen.
Importing the user32.dll, and simulating the key-press will only work, if executed on a windows client - locally, not from azure. There are some full screen options for browsers - but I am not sure if they fit you case. Video playback components are able to request full screen; you might want to dig into that.
Otherwise, if you target a specific OS or browser, you can create a custom client side app or plugin.
As for the javascript part, you can find an example here: https://www.w3schools.com/howto/howto_js_fullscreen.asp, but I am not sure if it will fit you requirements.
Here's one of the examples:
source: https://www.w3schools.com/howto/howto_js_fullscreen.asp
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
/* Chrome, Safari and Opera syntax */
:-webkit-full-screen {
background-color: yellow;
}
/* Firefox syntax */
:-moz-full-screen {
background-color: yellow;
}
/* IE/Edge syntax */
:-ms-fullscreen {
background-color: yellow;
}
/* Standard syntax */
:fullscreen {
background-color: yellow;
}
/* Style the button */
button {
padding: 20px;
font-size: 20px;
}
</style>
</head>
<body>
<h2>Fullscreen with JavaScript</h2>
<p>Click on the "Open Fullscreen" button to open this page in fullscreen mode. Close it by either clicking the "Esc" key on your keyboard, or with the "Close Fullscreen" button.</p>
<button onclick="openFullscreen();">Open Fullscreen</button>
<button onclick="closeFullscreen();">Close Fullscreen</button>
<script>
var elem = document.documentElement;
function openFullscreen() {
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.mozRequestFullScreen) { /* Firefox */
elem.mozRequestFullScreen();
} else if (elem.webkitRequestFullscreen) { /* Chrome, Safari & Opera */
elem.webkitRequestFullscreen();
} else if (elem.msRequestFullscreen) { /* IE/Edge */
elem.msRequestFullscreen();
}
}
function closeFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
</script>
<p>Note: Internet Explorer 10 and earlier does not support the msRequestFullscreen() method.</p>
</body>
</html>

C# Selenium Webdriver Find Element Within Iframe

I am having trouble finding an iframe. I want to switch to this iframe then click on an element within it.
I have tried finding the iframe using Id, Xpath, TagName, and CssSelector but my test times out while looking for the element each time.
This is the iframe as it appears in the page source:
<div xmlns="http://www.w3.org/1999/xhtml" id="dashboardView" style="display: block;">
<iframe id="dashboardViewFrame" border="0" scrolling="no" frameborder="0"
style="visibility: visible; height: 607px; width: 1280px; background-color: transparent;"
src="HtmlViewer.ashx?Dd_ContentId=6a8a44ae-2bd5-4f3c-8583-e777279ad4f2"></iframe>
</div>
<iframe xmlns="http://www.w3.org/1999/xhtml" id="dashboardViewFrame" border="0" scrolling="no"
frameborder="0" style="visibility: visible; height: 607px; width: 1280px; background-color:
transparent;" src="HtmlViewer.ashx?Dd_ContentId=6a8a44ae-2bd5-4f3c-8583-e777279ad4f2"></iframe>
Here is my current code:
public static bool IsAt
{
get
{
try
{
var dashboardiFrame = Driver.Instance.FindElement(By.Id("dashboardViewFrame"));
//todo switch to iframe
//todo find element within iframe
return true;
}
catch
{
return false;
}
}
}
Can someone please suggest a way to find the iframe and switch to it?
some times you have to sleep around 5 second till page load completely then find frame.
try this
thread.sleep(50000);
IwebElement Frame = Driver.SwitchTo().Frame("id of the frame");
//then any element inside frame should get by this line
Frame.FindElement(By.id("ID of element inside frame");
The main problem was that my test opened a new window, but my test was looking for elements on the old window. I resolved that by switching to the new page using:
Driver.Instance.SwitchTo().Window(Driver.Instance.WindowHandles.Last());
Then I could switch to the iframe also by also using SwitchTo() as shown below:
public static bool IsAt
{
get
{
try
{
Driver.Instance.SwitchTo().Window(Driver.Instance.WindowHandles.Last());
var DBViFrame = Driver.Instance.FindElement(By.Id("dashboardViewFrame"));
Driver.Instance.SwitchTo().Frame(DBViFrame);
var dataEntryButton = Driver.Instance.FindElement(By.Id("HyperlinkDataEntry"));
dataEntryButton.Click();
return true;
}
catch(Exception ex)
{
return false;
}
}
}

Scrolling Dynamic DIV

I have a DIV which has images and hyperlinks, which are added in C# by CODE
mStr.Append(" <div id='wn'>");
mStr.Append("<div id='lyr1'> <ul id='horiz'>");
if (dv.Count > 0) {
for (int i = 0; i < dv.Count; i++) {
mStr.Append("<li width='450' height='110' style='padding-left:5px; padding-right:5px; padding-top:2px; padding-bottom:2px;'>");
mStr.Append("<a href='PlayGame.aspx?GameID=" + GameLib.Utilities.Encrypt(dv[i][1].ToString()) + "'>");
mStr.Append("<img src='../" + dv[i][10].ToString() + "' width='156px' height='109px' style='padding-left:0px;' />");
mStr.Append("</a>");
mStr.Append("</li>");
}
mStr.Append("</ul></div></div>");
RelatedGames.InnerHtml.Remove(0, RelatedGames.InnerHtml.Length);
RelatedGames.InnerHtml = mStr.ToString();
}
..but the problem is that I want to scroll the DIV so that i can go through all images. I tried many ways in JQuery but it has been stuck and static. I will be grateful for any suggestions.
Or, is there any other way that the same functionality can be achieved?
Simply add the following CSS:
#lyr1 {
overflow: auto;
}
Overflow is a CSS property that specifies how content that is larger than its parents should be displayed. The default value is visible, which means that everything will be displayed, even if it goes beyond the size of its parent (which it does, in your case). Setting it to auto will make everything that doesn't fit in the parent hidden, and will add scrollbars whenever necessary. To make scrollbars always visible, do overflow: scroll;.
Live demo: http://jsfiddle.net/DanVicBez/kNk4y/
Just use a css property overflow:scroll to the target div
<div id='lyr1' style='overflow:scroll'>

Dynamically Changing HTML

I am trying to create a HTML page where the "body" color changes depending on some data being gathered from the RAM. If the RAM fills up beyond a certain threshold then I want the color to change.
<body style="background-color:<%=
if(MemoryPercentage < 33)
{
//set to green.
}
else if(MemoryPercentage < 66)
{
//set to yellow.
}
else
{
//set to red.
}%>">
Thank you for your help,
Aaron
<body
style="background-color:<%= MemoryPercentage < 33? "green":
(MemoryPercentage < 66? "yellow":"red") %>;">
I'd prefer using CSS classes and separating the logic out so it is more readable.
<style type="text/css">
.warn {
background-color: #00ffff;
}
.error {
background-color: #ff0000;
}
.ok {
background-color: #00ff00;
}
</style>
<%
var klass = MemoryPercentage < 33 : "ok" ? (MemoryPercentage < 66 ? "warn" : "error");
%>
<body class="<%= klass %>">
While you can definitely apply the style directly using the sytle attribute of the body tag (as suggested in this answer), general best practices revolving around HTML discourage this.
What you should do is place these styles in a stylesheet which is referenced on your page, and then have different names for the classes.
Then, in your code, apply the class that has the style you want depending on your logic to the class attribute of the body element.
Just an aside to the other answers:
<body id="Body" runat="server"> will make the tag accessible to Page_Load() & friends as an HtmlGenericControl, so you can handle the logic and set Body.CssClass without the template-y markup. Makes it a little less messy / easier to maintain.

Upload an image with wmd?

Is it possible with the wmd editor to add a button to let the user upload an image to the web server and place the corresponding img markdown in the textbox? If not, will another good inplace editor do it? Context: I'm using asp.net mvc, C# and I am a true beginner with javascript.
A brief perusal of the WMD seems to indicate that this feature is not supported directly and that the control is not particularly pluggable.
That being said, there's nothing stopping you from creating a button/upload-field/whatever that sends an image to your servers and injects the appropriate:
<img src="http://your.server.com/path/to/attachments/..." />
Into the control's underlying textarea.
Here's a variation to the minimal example that comes with WMD:
<!DOCTYPE html>
<html>
<head>
<title>WMD minimal example</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"></script>
<script type="text/javascript">
$.fn.insertAtCaret = function (myValue) {
return this.each(function(){
//IE support
if (document.selection) {
this.focus();
sel = document.selection.createRange();
sel.text = myValue;
this.focus();
}
//MOZILLA/NETSCAPE support
else if (this.selectionStart || this.selectionStart == '0') {
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
var scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos)
+ myValue
+ this.value.substring(endPos,
this.value.length);
this.focus();
this.selectionStart = startPos + myValue.length;
this.selectionEnd = startPos + myValue.length;
this.scrollTop = scrollTop;
} else {
this.value += myValue;
this.focus();
}
});
};
int i = 50;
function Add()
{
$("#myTextarea").insertAtCaret("![alt text][" +(i++)+"]");
// You'll need to add the link too, at the bottom
}
</script>
</head>
<body>
<form>
test
<textarea id="myTextarea" style="width: 500px; height: 200px;">*This* is a minimal example.</textarea>
</form>
<div class="wmd-preview"></div>
<script type="text/javascript" src="wmd/wmd.js"></script>
</body>
</html>
But it's only the beginnings as you can probably tell. This markdown editor looks better
I wrote a blog post that explains how I solved this. In the post, I use PHP - if you're comfortable converting my PHP logic into ASP.NET, you may find it helpful!

Categories