# Printable Invoice and Packing Slip From the Order Screen

> Adds "Print invoice" and "Print packing slip" links to each order in the admin, opening a clean printable page without a PDF plugin.

- Type: PHP
- Runs: Run everywhere
- Category: [WooCommerce](https://wpide.com/library/category/woocommerce/)
- Requires: WooCommerce
- Tags: woocommerce, invoices, packing-slip, admin
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/woo-printable-invoice-packing-slip/

## Code

```php
add_action( 'woocommerce_admin_order_data_after_order_details', function ( $order ) {
    $base = array( 'action' => 'wpide_print_order', 'order_id' => $order->get_id() );
    $url  = function ( $type ) use ( $base, $order ) {
        return wp_nonce_url( add_query_arg( $base + array( 'type' => $type ), admin_url( 'admin-post.php' ) ), 'wpide_print_' . $order->get_id() );
    };

    printf(
        '<p class="form-field form-field-wide"><a class="button" target="_blank" href="%1$s">%2$s</a> <a class="button" target="_blank" href="%3$s">%4$s</a></p>',
        esc_url( $url( 'invoice' ) ),
        esc_html( 'Print invoice' ),
        esc_url( $url( 'packing' ) ),
        esc_html( 'Print packing slip' )
    );
} );

add_action( 'admin_post_wpide_print_order', function () {
    $order_id = isset( $_GET['order_id'] ) ? absint( $_GET['order_id'] ) : 0;
    $type     = isset( $_GET['type'] ) && 'packing' === $_GET['type'] ? 'packing' : 'invoice';

    check_admin_referer( 'wpide_print_' . $order_id );

    if ( ! current_user_can( 'edit_shop_orders' ) ) {
        wp_die( esc_html( 'You are not allowed to print this order.' ), 403 );
    }

    $order = wc_get_order( $order_id );

    if ( ! $order ) {
        wp_die( esc_html( 'Order not found.' ), 404 );
    }

    $title   = 'packing' === $type ? 'Packing slip' : 'Invoice';
    $invoice = $order->get_meta( '_wpide_invoice_number' );
    ?>
    <!doctype html>
    <html lang="<?php echo esc_attr( get_bloginfo( 'language' ) ); ?>">
    <head>
        <meta charset="utf-8">
        <title><?php echo esc_html( $title . ' ' . $order->get_order_number() ); ?></title>
        <style>
            body{font:14px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;color:#111;max-width:800px;margin:2em auto;padding:0 1em}
            h1{font-size:24px;margin:0 0 .25em}table{width:100%;border-collapse:collapse;margin:1.5em 0}
            th,td{text-align:left;padding:.5em;border-bottom:1px solid #ddd;vertical-align:top}.num{text-align:right}
            .cols{display:flex;gap:2em;flex-wrap:wrap}.cols>div{flex:1;min-width:200px}
            @media print{.no-print{display:none}body{margin:0}}
        </style>
    </head>
    <body>
        <p class="no-print"><button onclick="window.print()"><?php echo esc_html( 'Print' ); ?></button></p>
        <h1><?php echo esc_html( $title ); ?></h1>
        <p>
            <strong><?php echo esc_html( get_bloginfo( 'name' ) ); ?></strong><br>
            <?php echo esc_html( implode( ', ', array_filter( array( WC()->countries->get_base_address(), WC()->countries->get_base_city(), WC()->countries->get_base_postcode() ) ) ) ); ?>
        </p>
        <p>
            <?php echo esc_html( 'Order: #' . $order->get_order_number() ); ?><br>
            <?php if ( $invoice && 'invoice' === $type ) : ?>
                <?php echo esc_html( 'Invoice: ' . $invoice ); ?><br>
            <?php endif; ?>
            <?php echo esc_html( 'Date: ' . wc_format_datetime( $order->get_date_created() ) ); ?>
        </p>
        <div class="cols">
            <div><h3><?php echo esc_html( 'Billing address' ); ?></h3><?php echo wp_kses_post( $order->get_formatted_billing_address() ); ?></div>
            <?php if ( $order->has_shipping_address() ) : ?>
                <div><h3><?php echo esc_html( 'Shipping address' ); ?></h3><?php echo wp_kses_post( $order->get_formatted_shipping_address() ); ?></div>
            <?php endif; ?>
        </div>
        <table>
            <thead><tr><th><?php echo esc_html( 'Product' ); ?></th><th><?php echo esc_html( 'SKU' ); ?></th><th class="num"><?php echo esc_html( 'Qty' ); ?></th><?php if ( 'invoice' === $type ) : ?><th class="num"><?php echo esc_html( 'Total' ); ?></th><?php endif; ?></tr></thead>
            <tbody>
            <?php foreach ( $order->get_items() as $item ) : ?>
                <?php $product = $item->get_product(); ?>
                <tr>
                    <td><?php echo esc_html( $item->get_name() ); ?><?php echo wp_kses_post( wc_display_item_meta( $item, array( 'echo' => false ) ) ); ?></td>
                    <td><?php echo esc_html( $product ? $product->get_sku() : '' ); ?></td>
                    <td class="num"><?php echo esc_html( $item->get_quantity() ); ?></td>
                    <?php if ( 'invoice' === $type ) : ?><td class="num"><?php echo wp_kses_post( $order->get_formatted_line_subtotal( $item ) ); ?></td><?php endif; ?>
                </tr>
            <?php endforeach; ?>
            </tbody>
            <?php if ( 'invoice' === $type ) : ?>
                <tfoot>
                <?php foreach ( $order->get_order_item_totals() as $row ) : ?>
                    <tr><th colspan="3" class="num"><?php echo esc_html( wp_strip_all_tags( $row['label'] ) ); ?></th><td class="num"><?php echo wp_kses_post( $row['value'] ); ?></td></tr>
                <?php endforeach; ?>
                </tfoot>
            <?php endif; ?>
        </table>
        <?php if ( $order->get_customer_note() ) : ?>
            <p><strong><?php echo esc_html( 'Customer note:' ); ?></strong> <?php echo esc_html( $order->get_customer_note() ); ?></p>
        <?php endif; ?>
    </body>
    </html>
    <?php
    exit;
} );
```

## Notes

Uses the browser's print dialog (which can save as PDF), leaves prices off the packing slip and shows invoice numbers from the sequential invoice snippet.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Printable Invoice and Packing Slip From the Order Screen" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
