Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9683

C#+Excel:選択したオートシェイプの文字列編集能力を奪い取る

$
0
0

オートシェイプのテキスト絡みで
・Excel2016で、矢印キーでIカーソルが見かけ上動かない問題
・Excel2013で、文字列表示とIカーソル位置が横方向に少しずれる問題
が、くそウザかったので、暫定対策すべくツールをつくってみた。1
(最新版のupdateあてれば治るのかもしれないが・・)

画面キャプチャ

image.png

使い方

  1. Get AutoShapeボタンを押す
  2. Excel上で文字列を含むオートシェイプをクリックして選択する
  3. Stop/Fixボタンを押す
  4. テキストを編集すると、Excel上のオートシェイプのテキストも連動して変化する

注意点

  • Excelのオートシェイプ上の文字列が、部分ごとに書式が違う場合、書式情報が抹消されます。
  • 編集対象のオートシェイプをもつExcelのシート閉じたりオートシェイプを消した状態でテキストを編集すると例外で落ちるはず。
  • Excel上でも編集できてしまい、アプリには反映されない。(タイトル詐欺)

コンパイル方法

Windows10 Excel2016環境
(Excelがインストールされてれば、環境違ってもC:\Windows\assembly\GAC_MSIL\以下をdir /s なんちゃら.dllで探せば出てくるはず。)

csc ^
 /r:C:\Windows\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll ^
 /r:C:\Windows\assembly\GAC_MSIL\office\15.0.0.0__71e9bce111e9429c\Office.dll ^
 %*

C#ソースコード

usingSystem;usingSystem.Drawing;//using System.Collections.Generic;//using System.Reflection;usingSystem.Runtime.CompilerServices;// to use [MethodImpl(MethodImplOptions.NoInlining)]usingSystem.Runtime.InteropServices;usingSystem.Text.RegularExpressions;usingSystem.Windows.Forms;usingExcel=Microsoft.Office.Interop.Excel;//using Microsoft.Office.Core;classExcelAutoshapeTest:Form{System.Windows.Forms.Timertimer;TextBoxtxtName;TextBoxtxtContent;ButtonbtnStartTryGet;dynamic_oShape;bool_updatedByProgram;[MethodImpl(MethodImplOptions.NoInlining)]staticvoidDumpTextOfActiveSheet(){varoExcelApp=(Excel.Application)Marshal.GetActiveObject("Excel.Application");varoSheet=(Excel.Worksheet)oExcelApp.ActiveWorkbook.ActiveSheet;varoShapes=(Excel.Shapes)oSheet.Shapes;foreach(Excel.ShapeoShapeinoShapes){Console.WriteLine(oShape.Type);if(oShape.Type==Microsoft.Office.Core.MsoShapeType.msoAutoShape){Console.WriteLine(oShape.AutoShapeType);try{dynamicoTextFrame=oShape.TextFrame;Console.WriteLine(oTextFrame.Characters.Text);}catch(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException){//Console.WriteLine(e);}catch(COMException){//Console.WriteLine(e);}}//oTextFrame.Characters.Text = "bbb";}}[MethodImpl(MethodImplOptions.NoInlining)]voidTryGetActiveAutoShape(){varoExcelApp=(Excel.Application)Marshal.GetActiveObject("Excel.Application");dynamict=oExcelApp.Selection;try{_updatedByProgram=true;_oShape=null;txtContent.Text=Regex.Replace(t.Characters.Text,@"\n","\r\n",RegexOptions.Multiline);txtName.Text=t.Name;_oShape=t;}catch(Exceptione){if(eisMicrosoft.CSharp.RuntimeBinder.RuntimeBinderException||eisCOMException){// Note: C#6以降なら when を使ってもう少しきれいに書ける_oShape=null;txtName.Text="";txtContent.Text="";// もみ消すreturn;}throwe;}finally{_updatedByProgram=false;}}voidUpdateExcelAutoShape(){if(_oShape!=null){strings=Regex.Replace(txtContent.Text,@"\r\n","\n",RegexOptions.Multiline);_oShape.Characters.Text=s;}}ExcelAutoshapeTest(){_oShape=null;Controls.Add(txtName=newTextBox(){Location=newPoint(0,0),Width=150,ReadOnly=true});Controls.Add(btnStartTryGet=newButton(){Text="Get AutoShape",Location=newPoint(180,0),Width=100});btnStartTryGet.Click+=(s,e)=>{if(timer.Enabled){((Button)s).Text="Get AutoShape";txtContent.ReadOnly=false;timer.Stop();}else{((Button)s).Text="Stop/Fix";txtContent.ReadOnly=true;timer.Start();}};Controls.Add(txtContent=newTextBox(){Location=newPoint(0,30),ScrollBars=ScrollBars.Both,Multiline=true,WordWrap=false});txtContent.TextChanged+=(s,e)=>{if(!_updatedByProgram){UpdateExcelAutoShape();}};Load+=(s,e)=>{MyResize();};Resize+=(s,e)=>{MyResize();};ResizeEnd+=(s,e)=>{MyResize();};timer=newSystem.Windows.Forms.Timer();timer.Interval=1000;timer.Tick+=(s,e)=>{TryGetActiveAutoShape();GC.Collect();GC.WaitForPendingFinalizers();};}voidMyResize(){intw=ClientSize.Width;inth=ClientSize.Height-txtContent.Top;if(w<50){w=50;}if(h<50){h=50;}txtContent.Size=newSize(w,h);}[STAThread]staticvoidMain(string[]args){//DumpTextOfActiveSheet();Application.Run(newExcelAutoshapeTest());}}

参考サイト


  1. そもそもExcelは表計算ツールなのでオートシェイプ使う事自体がおかしなことかもしれない 


Viewing all articles
Browse latest Browse all 9683

Trending Articles