frappe / books

Free Accounting Software
https://frappe.io/books
GNU Affero General Public License v3.0
2.97k stars 682 forks source link

Print Invoice Directly Using Print Button #785

Open hafeesk opened 11 months ago

hafeesk commented 11 months ago

Now we can not print invoice directly,we need to download pdf and print .Print Directly From Print Button

mildred commented 11 months ago

This requires more cooperation with the system, hence this is probably not trivial.

dvodev commented 10 months ago

I have added this functionality locally

Sunitsarode commented 9 months ago

I have added this functionality locally

Hi can you please contribute your code to main branch. It is most required facility

Elanngo-Madheswaran commented 2 months ago

Is this still working in progress or left behind ?

Elanngo-Madheswaran commented 2 months ago

@dvodev could you tell me how did you do it locally so that I could do that , even if it unstable no problem

Elanngo-Madheswaran commented 2 months ago

i changed the saveHtmlasPdf.ts file for now I havent worked on it much but it says you to save the pdf and when you click the save button it doesnt save and just open print window,

this is the changed code , I dont know if its correct or wrong but it works I guess

import { App, BrowserWindow } from 'electron';
import fs from 'fs/promises';
import path from 'path';

export async function saveHtmlAsPdf(
  html: string,
  savePath: string,
  app: App,
  width: number, // centimeters
  height: number // centimeters
): Promise<boolean> {
  /**
   * Store received html as a file in a tempdir,
   * this will be loaded into the print view
   */
  const tempRoot = app.getPath('temp');
  const filename = path.parse(savePath).name;
  const htmlPath = path.join(tempRoot, `${filename}.html`);
  await fs.writeFile(htmlPath, html, { encoding: 'utf-8' });

  const printWindow = await getInitializedPrintWindow(htmlPath, width, height);

  // Define print options
  const printOptions = {
    silent: false, // False to show print dialog
    printBackground: true, // Print background graphics
  };

  // Trigger the print dialog (prints to selected printer instead of saving a PDF)
  printWindow.webContents.print(printOptions, (success, errorType) => {
    if (!success) {
      console.error(`Printing failed: ${errorType}`);
    }
  });

  // Close the hidden window after printing
  printWindow.on('closed', () => {
    printWindow.destroy();
  });

  // Clean up the temporary HTML file
  await fs.unlink(htmlPath);

  return true;
}

async function getInitializedPrintWindow(
  printFilePath: string,
  width: number,
  height: number
) {
  const printWindow = new BrowserWindow({
    width: Math.floor(width * 28.333333), // pixels
    height: Math.floor(height * 28.333333), // pixels
    show: false, // Window is hidden during printing
  });

  await printWindow.loadFile(printFilePath);
  return printWindow;
}
xcode-ae commented 1 month ago

hello, this feature is really very important and i'm also looking for this option, "print without saving as PDF"

i have tried your code and it's working fine but still showing for saving as PDF but after that you are right no pdf has been saved only redirect me to popup for printing which is very good for now. i hope we can continue on it

dvodev commented 1 month ago

This is only on a windows machine working using the system properties. This is not something that should be put merged into master

Thank You, Dakota Vogt

On Sun, Sep 29, 2024 at 9:53 AM Xcode Technology @.***> wrote:

hello, this feature is really very important and i'm also looking for this option, "print without saving as PDF"

— Reply to this email directly, view it on GitHub https://github.com/frappe/books/issues/785#issuecomment-2381366456, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANA43WEHM27UYU2RXQOQTSLZZAA5VAVCNFSM6AAAAABAOKU5WGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGOBRGM3DMNBVGY . You are receiving this because you were mentioned.Message ID: @.***>

Elanngo-Madheswaran commented 1 month ago

Hi @dvodev,

I wanted to let you know that the fix I implemented is just a temporary solution for your local system. I understand that it won't be merged into the main branch. If I intended for it to be merged, I would have made more comprehensive changes, including altering the buttons and other elements.

Thank you for responding though

Elanngo-Madheswaran commented 1 month ago

hello, this feature is really very important and i'm also looking for this option, "print without saving as PDF"

i have tried your code and it's working fine but still showing for saving as PDF but after that you are right no pdf has been saved only redirect me to popup for printing which is very good for now. i hope we can continue on it

i made another version of the code where it will open the temp pdf in edge browser there you can select to print or save as pdf and When you close the temp file will be automatically deleted , but the code needs to altered according to your system (the adddress of the edge browser exe) if you want i could send that too

xcode-ae commented 1 month ago

hello, this feature is really very important and i'm also looking for this option, "print without saving as PDF" i have tried your code and it's working fine but still showing for saving as PDF but after that you are right no pdf has been saved only redirect me to popup for printing which is very good for now. i hope we can continue on it

i made another version of the code where it will open the temp pdf in edge browser there you can select to print or save as pdf and When you close the temp file will be automatically deleted , but the code needs to altered according to your system (the adddress of the edge browser exe) if you want i could send that too

Sounds good, and I appreciate your help and support. I was already thinking that since Frappe Books uses a web version, why not add this feature for people who prefer not to save the PDF, helping them conserve storage as the app is used locally. BTW im using Macbook and chrome browser and already there is an option for saving or printing by itself and if you share the code it will be great too !

Elanngo-Madheswaran commented 1 month ago

if you share the code it will be great too !

import { App } from 'electron';
import fs from 'fs/promises';
import path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';

const execPromise = promisify(exec);

export async function saveHtmlAsPdf(
  html: string,
  savePath: string,
  app: App,
  width: number, // centimeters
  height: number // centimeters
): Promise<boolean> {
  try {
    // Store HTML as a file in a temp directory
    const tempRoot = app.getPath('temp');
    const filename = path.parse(savePath).name;
    const htmlPath = path.join(tempRoot, `${filename}.html`);
    await fs.writeFile(htmlPath, html, { encoding: 'utf-8' });

    // Path to Edge executable
    const edgePath = `C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe`; // edit the path according to your computer

    // Command to open Edge with the print preview for the HTML file
    const command = `"${edgePath}" --print --no-margins "${htmlPath}"`;

    // Execute the command to open Edge
    await execPromise(command);

    // Clean up the temporary HTML file
    // Use a timeout to ensure Edge has enough time to open before deleting the file
    setTimeout(async () => {
      try {
        await fs.unlink(htmlPath);
      } catch (error) {
        if (error instanceof Error) {
          console.error(`Failed to delete temp HTML file: ${error.message}`);
        } else {
          console.error('Failed to delete temp HTML file: Unknown error');
        }
      }
    }, 5000); // 5 seconds delay to ensure Edge has time to process

    return true;
  } catch (error) {
    if (error instanceof Error) {
      console.error(`Failed to save HTML as PDF: ${error.message}`);
    } else {
      console.error('Failed to save HTML as PDF: Unknown error');
    }
    return false;
  }
}

You can edit this code according to your computer file arrangement

xcode-ae commented 1 month ago

if you share the code it will be great too !

import { App } from 'electron';
import fs from 'fs/promises';
import path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';

const execPromise = promisify(exec);

export async function saveHtmlAsPdf(
  html: string,
  savePath: string,
  app: App,
  width: number, // centimeters
  height: number // centimeters
): Promise<boolean> {
  try {
    // Store HTML as a file in a temp directory
    const tempRoot = app.getPath('temp');
    const filename = path.parse(savePath).name;
    const htmlPath = path.join(tempRoot, `${filename}.html`);
    await fs.writeFile(htmlPath, html, { encoding: 'utf-8' });

    // Path to Edge executable
    const edgePath = `C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe`; // edit the path according to your computer

    // Command to open Edge with the print preview for the HTML file
    const command = `"${edgePath}" --print --no-margins "${htmlPath}"`;

    // Execute the command to open Edge
    await execPromise(command);

    // Clean up the temporary HTML file
    // Use a timeout to ensure Edge has enough time to open before deleting the file
    setTimeout(async () => {
      try {
        await fs.unlink(htmlPath);
      } catch (error) {
        if (error instanceof Error) {
          console.error(`Failed to delete temp HTML file: ${error.message}`);
        } else {
          console.error('Failed to delete temp HTML file: Unknown error');
        }
      }
    }, 5000); // 5 seconds delay to ensure Edge has time to process

    return true;
  } catch (error) {
    if (error instanceof Error) {
      console.error(`Failed to save HTML as PDF: ${error.message}`);
    } else {
      console.error('Failed to save HTML as PDF: Unknown error');
    }
    return false;
  }
}

You can edit this code according to your computer file arrangement

Awesome, thank you very much !