Code: Word Addin with photos resize and paste in Word
The following code example creates a Word Addin that inserts photos into a Word file at a specific location or table with a target.
The photos are scaled down in Windows and inserted into a new table behind the position target.
contains:
Word Intercom Addin, Ribbonbar
Resize Image Bitmap and Graphics Interface
DoEvents in Window Forms, WPF, C #
STA single thread
With insert dialog
The software code is as a project in a zip file attached to the download
Code Example:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Office.Tools.Ribbon;
//----< using >---- //using Microsoft.Office.Tools.Ribbon; //*word ribbon using Word = Microsoft.Office.Interop.Word; //*word document using System.Windows.Forms; //*word OpenfileDialog using Office = Microsoft.Office.Core; //*lock ratio width height using Microsoft.Office.Interop.Word; using System.Threading.Tasks; using System.Threading;
using System.Drawing; //*compress photo by windows using System.Drawing.Imaging; //*compress photo by windows using System.Drawing.Drawing2D; //*compress quality
//----</ using >----
namespace Addin_Word_Photos_into_Table { public partial class Ribbon1 { //< init > Document _doc = null; Word.Application _app = null; const string _Table_Key = "Photos_Addin"; const string _Table_Font = "Arial"; const int _Table_Font_Size = 11;
//</ init >
//< leeres Delegate erstellen > private delegate void DoEvents_EmptyDelegate(); //</ leeres Delegate erstellen >
#region Region: Ribbonbar //===================< RibbonBar >=================== private void Ribbon1_Load(object sender, RibbonUIEventArgs e) { //tbxPhotos_Tablename.Text = Settings1.Default.Photos_Tablename; } //===================</ RibbonBar >=================== #endregion /Ribbonbar
#region --Button-- //===================< Buttons >=================== private void BtnPhotos_Insert_Click(object sender, RibbonControlEventArgs e) { _doc = Globals.ThisAddIn.Application.ActiveDocument; _app = Globals.ThisAddIn.Application;
//< init setup > string sInsert_Type = Settings1.Default.Insert_Type; string sTargetname = Settings1.Default.Target_Label; //</ init setup >
Word.Table table_Photos; table_Photos = find_Table_Filled(); if(table_Photos==null) { if (sInsert_Type.IndexOf("Nach Textzeile") >-1) { table_Photos = find_Textline_Create_Empty_Table(sTargetname); } else { table_Photos = find_Table_with_Header(sTargetname); } } if (table_Photos != null) { insert_Photos_at_Table(table_Photos); } }
//}
private void btnSetup_Click(object sender, RibbonControlEventArgs e) { frmSetup frm = new frmSetup(); frm.Show(); } //===================</ Buttons >=================== #endregion /Buttons
#region --Methods-- //===================< Methods >=================== private Word.Table find_Table_Filled() { //-----------------< find_Table_Filled() >-----------------
//--< find Table Header >-- //*Loop all tables and ID in Description foreach (Word.Table table in _doc.Tables) { if (table.Rows.Count > 0) { if (table.Descr == _Table_Key) { return table; } } } //< check > return null; //--</ find Table Header >-- //-----------------</ find_Table_Filled() >----------------- }
private Word.Table find_Table_with_Header(string sHeader) { //-----------------< find_Table_with_Header() >-----------------
//--< find Table Header >-- //*Loop all tables and look for header foreach (Word.Table table in _doc.Tables) { if (table.Rows.Count > 0) { int intColumns_Count = table.Columns.Count; for (int iCol = 1; iCol <= intColumns_Count; iCol++) { //----< @Loop: Columns in Table_Header >---- Cell cell = null; try { cell = table.Cell(1, iCol); if (cell.Range.Text.IndexOf(sHeader) == 0) { table.Descr= _Table_Key; return table; } } catch (Exception) { //< endofcolumns > break; //</ endofcolumns > } //----</ @Loop: Columns in Table_Header >---- } } } //< check > System.Windows.Forms.MessageBox.Show("Tabelle mit Header nicht gefunden. " + Environment.NewLine + "gesuchter Header:" + sHeader, "Header nicht gefunden"); return null; //--</ find Table Header >-- //-----------------</ find_Table_with_Header() >----------------- }
private Word.Table find_Textline_Create_Empty_Table(string sHeader) { //-----------------< find_Table_with_Header() >-----------------
//--< find Table Header >-- //*Loop all tables and look for header foreach (Word.Range sLine in _doc.Sentences) { //-------< Check Sentence >------ string sText = sLine.Text;
//< check: Zeilenumbruch > int posUmbruch = sText.IndexOf("\r"); if (posUmbruch>0) { sText = sText.Substring(0, posUmbruch); } posUmbruch = sText.IndexOf("\n"); if (posUmbruch > 0) { sText = sText.Substring(0, posUmbruch); } //</ check: Zeilenumbruch >
sText = sText.Trim(); if (sText == sHeader ) { //----< Line_found >---- sLine.End= sLine.Start+sText.Length; sLine.Select(); _app.Selection.Select(); _app.Selection.EndKey(); sLine.InsertAfter("\n\r"); _app.Selection.MoveDown(); _app.Selection.MoveDown(); Range newRange = _app.Selection.Range; _app.ScreenRefresh();
//< init setup > int Columns_Count = Settings1.Default.Columns_Count; //</ init setup >
//< create new table > Word.Table newTable = _doc.Tables.Add( newRange ,NumRows:1,NumColumns: Columns_Count); newTable.Range.Font.Name = _Table_Font; newTable.Range.Font.Size=_Table_Font_Size; newTable.Range.Font.Bold = 0; newTable.Range.Font.Underline = 0; newTable.Descr = _Table_Key; //</ create new table >
//< out > return newTable; //</ out > //----</ Line_found >---- } //-------</ Check Sentence >------ } //< check > System.Windows.Forms.MessageBox.Show("Zeile nicht gefunden. " + Environment.NewLine + "gesuchter Header:" + sHeader, "Header nicht gefunden"); return null; //--</ find Table Header >-- //-----------------</ find_Table_with_Header() >----------------- }
private async void insert_Photos_at_Table(Word.Table table_Photos) { //-----------------< insert_Photos_by_TableHeader() >-----------------
//< init > int intColumns_count = table_Photos.Columns.Count; //</ init >
//--< Word-FileDialog >-- OpenFileDialog fileDialog = new OpenFileDialog(); fileDialog.Filter = "image files (*.bmp;*.jpg;*.jpeg;*.png;*.gif;*.tif;*.tiff)|*.bmp;*.jpg;*.jpeg;*.png;*.gif;*.tif;*.tiff"; fileDialog.Multiselect = true; //fileDialog.InitialDirectory = "B:\\2016"; var result = fileDialog.ShowDialog(); //--</ Word-FileDialog >--
//< check > //*no file if (result != System.Windows.Forms.DialogResult.OK) { return; } //</ check >
//< init setup > bool With_Filename = Settings1.Default.Show_Filename; bool With_Empty_Line = Settings1.Default.With_Empty_Line; int Columns_count = Settings1.Default.Columns_Count; string sInsert_Type = Settings1.Default.Insert_Type; string Compress_Type = Settings1.Default.Compress_Type; //</ init setup >
//--< check exits Entries >-- try { Row row = table_Photos.Rows.Last; if (row.Range.InlineShapes.Count > 0) { table_Photos.Rows.Add(); } } catch (Exception) { } //--</ check exits Entries >--
//-------< @Loop: Insert all Images >-------- int iCol = 0; foreach (String sfileName in fileDialog.FileNames) { //------< Loop.Item >------ iCol++; if (iCol > 2) { iCol = 1; table_Photos.Rows.Add(); } int iRow = table_Photos.Rows.Count;
Cell cell = table_Photos.Cell(iRow, iCol); float image_Width = cell.Width - cell.RightPadding - cell.LeftPadding; //< get selection > Range act_Image_Range = cell.Range; //</ get selection >
if(Compress_Type=="Windows") { load_Photo_compressed_to_Clipboard(sfileName, Convert.ToInt32( image_Width)); try { act_Image_Range.PasteSpecial(DataType: Word.WdPasteDataType.wdPasteBitmap, Placement: Word.WdOLEPlacement.wdInLine, DisplayAsIcon: false, Link: false); } catch (Exception) {
//throw; } act_Image_Range.Start = act_Image_Range.Start - 1; act_Image_Range.Select(); if (act_Image_Range.InlineShapes.Count>0) {
//< scale > act_Image_Range.InlineShapes[1].LockAspectRatio = Office.MsoTriState.msoTrue; act_Image_Range.InlineShapes[1].Width = image_Width; //</ scale > } } else { //----< Insert Image >---- //< insert picture from Link > Word.InlineShape inlineShape = _doc.InlineShapes.AddPicture(sfileName, LinkToFile: false, SaveWithDocument: true, Range: act_Image_Range); //</ insert picture from Link >
//< scale > inlineShape.LockAspectRatio = Office.MsoTriState.msoTrue; inlineShape.Width = image_Width; //</ scale > if (Compress_Type == "Word") { //--< replace as png >-- //*reduce memory 1 MB to 1kb //< cut > inlineShape.Select(); _app.Selection.Cut(); //</ cut >
//*pasteBitmap is much smaller act_Image_Range.PasteSpecial(Link: false, DataType: Word.WdPasteDataType.wdPasteBitmap, Placement: Word.WdOLEPlacement.wdInLine, DisplayAsIcon: false); act_Image_Range.Select(); //--</ replace as png >-- } //----</ Insert Image >---- } await DoEvents();
//--< Filename >-- if (With_Filename) { int posFilename = sfileName.LastIndexOf("\\"); if(posFilename>-1) { string sFileName_Short = sfileName.Substring(posFilename+1); _app.Selection.Select(); _app.Selection.EndKey(); _app.Selection.Font.Name = _Table_Font; _app.Selection.Font.Size = _Table_Font_Size; _app.Selection.Font.Bold = 0; _app.Selection.Font.Underline = 0; _app.Selection.TypeParagraph(); _app.Selection.TypeText(sFileName_Short); } } //--</ Filename >--
//--< Empty_Line >-- if (With_Empty_Line) { //_app.Selection.EndKey(); _app.Selection.TypeParagraph(); } //--</ Empty_Line >--
_app.ScreenRefresh(); _app.ScreenUpdating = true; } //-------</ @Loop: Insert all Images >--------
//-----------------</ insert_Photos_at_Table_with_Header() >----------------- }
//===================</ Methods >=================== #endregion /Methods
protected async Task<bool> DoEvents()
{
//----< DoEvents() >----
//* Diese Funktion uebernimmt die Unterbrechnung zur Anzeige und Eventbearbeitung in C#, WPF beim langen Loop Berechnungen //* mit einer Dispatcher //* EmptyDelegate im Header definieren //* using System.Windows.Threading; im Header festlegen
//Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new DoEvents_EmptyDelegate(delegate { }));
await System.Threading.Tasks.Task.Run(() => {
Thread.Sleep(1);
});
return true;
//----</ DoEvents() >----
}
private void load_Photo_compressed_to_Clipboard_old(string sFilename,int setWidth=200) { // Create a bitmap. Bitmap loaded_Bitmap = new Bitmap(sFilename);
// Retrieve the bitmap data from the bitmap. BitmapData bitmapData = loaded_Bitmap.LockBits(new System.Drawing.Rectangle(0, 0, loaded_Bitmap.Width, loaded_Bitmap.Height), ImageLockMode.ReadOnly, loaded_Bitmap.PixelFormat);
float newHeight = setWidth * ((float)loaded_Bitmap.Height / loaded_Bitmap.Width); int setHeight = Convert.ToInt32(newHeight); //Create a new bitmap. Bitmap newBitmap = new Bitmap(200,200, bitmapData.Stride, loaded_Bitmap.PixelFormat, bitmapData.Scan0);
loaded_Bitmap.UnlockBits(bitmapData);
Clipboard.SetImage(newBitmap); }
public static void load_Photo_compressed_to_Clipboard(string input_Image_Path, int setLength) { //---------------< Image_resize() >--------------- Bitmap source_Bitmap = new Bitmap(input_Image_Path);
double dblWidth_origial = source_Bitmap.Width; double dblHeigth_origial = source_Bitmap.Height;
//< check orientation > bool IsOrientation_Horizontal = (dblWidth_origial > dblHeigth_origial) ? true : false; //</ check orientation >
int new_Height = 0; int new_Width = 0; double zoom_factor = 1; if (IsOrientation_Horizontal == true) { new_Width = setLength; zoom_factor = new_Width / dblWidth_origial; new_Height = (int)(dblHeigth_origial * zoom_factor); } else { new_Height = setLength; zoom_factor = new_Height / dblHeigth_origial; new_Width = (int)(dblWidth_origial * zoom_factor); }
Image outImage = new Bitmap(source_Bitmap, new_Width, new_Height); var t = new Thread((ThreadStart)(() => { Clipboard.SetImage(outImage); })); t.SetApartmentState(ApartmentState.STA); t.Start(); t.Join();
//---------------</ Image_resize() >--------------- } //----------------------------------</ Class >----------------------------------
} }
|
Ribbonbar:
File: Ribbon1.cs
The ribbon bar is created by the designer. The code is not inserted here
File: Settings1.settings
Settings Setup Code
File: frmSetup.cs
The settings are inserted in a setup.
using System; using System.Windows.Forms;
namespace Addin_Word_Photos_into_Table { public partial class frmSetup : Form {
#region Region: Window //===================< Region: Window >=================== public frmSetup() { InitializeComponent();
//< init > tbxTargetlabel.Text= Settings1.Default.Target_Label; cbxShow_Photo_Label.Checked= Settings1.Default.Show_Filename; ctlInsert_Type.SelectedItem = Settings1.Default.Insert_Type; ctlCompress.SelectedItem = Settings1.Default.Compress_Type; cbxEmptyLine.Checked= Settings1.Default.With_Empty_Line; cbxEmptyLine.Checked=Settings1.Default.With_Empty_Line ; ctlColumns.Value= (int) Settings1.Default.Columns_Count ; //</ init > } //===================</ Region: Window >=================== #endregion /Region: Window
#region Region: Controls //===================< Region: Controls >=================== private void tbxTargetlabel_TextChanged(object sender, EventArgs e) { Settings1.Default.Target_Label = tbxTargetlabel.Text; } private void ctlInsert_Type_SelectedIndexChanged(object sender, EventArgs e) { Settings1.Default.Insert_Type = ctlInsert_Type.SelectedItem.ToString(); } private void ctlCompress_SelectedIndexChanged(object sender, EventArgs e) { Settings1.Default.Compress_Type = ctlCompress.SelectedItem.ToString(); }
private void cbxShow_Photo_Label_CheckedChanged(object sender, EventArgs e) { Settings1.Default.Show_Filename = cbxShow_Photo_Label.Checked; }
private void cbxEmptyLine_CheckedChanged(object sender, EventArgs e) { Settings1.Default.With_Empty_Line = cbxEmptyLine.Checked; }
private void ctlColumns_ValueChanged(object sender, EventArgs e) { Settings1.Default.Columns_Count = (int) ctlColumns.Value; }
//===================</ Region: Controls >=================== #endregion /Region: Controls
} }
|