オートシェイプのテキスト絡みで
・Excel2016で、矢印キーでIカーソルが見かけ上動かない問題
・Excel2013で、文字列表示とIカーソル位置が横方向に少しずれる問題
が、くそウザかったので、暫定対策すべくツールをつくってみた。1
(最新版のupdateあてれば治るのかもしれないが・・)
画面キャプチャ
使い方
- Get AutoShapeボタンを押す
- Excel上で文字列を含むオートシェイプをクリックして選択する
- Stop/Fixボタンを押す
- テキストを編集すると、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#ソースコード
using System;
using System.Drawing;
//using System.Collections.Generic;
//using System.Reflection;
using System.Runtime.CompilerServices; // to use [MethodImpl(MethodImplOptions.NoInlining)]
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
//using Microsoft.Office.Core;
class ExcelAutoshapeTest : Form
{
System.Windows.Forms.Timer timer;
TextBox txtName;
TextBox txtContent;
Button btnStartTryGet;
dynamic _oShape;
bool _updatedByProgram;
[MethodImpl(MethodImplOptions.NoInlining)]
static void DumpTextOfActiveSheet()
{
var oExcelApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
var oSheet = (Excel.Worksheet)oExcelApp.ActiveWorkbook.ActiveSheet;
var oShapes = (Excel.Shapes)oSheet.Shapes;
foreach ( Excel.Shape oShape in oShapes ) {
Console.WriteLine(oShape.Type);
if (oShape.Type == Microsoft.Office.Core.MsoShapeType.msoAutoShape) {
Console.WriteLine(oShape.AutoShapeType);
try {
dynamic oTextFrame = 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)]
void TryGetActiveAutoShape()
{
var oExcelApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
dynamic t = 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(Exception e) {
if (e is Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ||
e is COMException ) { // Note: C#6以降なら when を使ってもう少しきれいに書ける
_oShape = null;
txtName.Text = "";
txtContent.Text = "";
// もみ消す
return;
}
throw e;
}
finally {
_updatedByProgram = false;
}
}
void UpdateExcelAutoShape()
{
if ( _oShape != null ) {
string s = Regex.Replace(txtContent.Text, @"\r\n", "\n", RegexOptions.Multiline);
_oShape.Characters.Text = s;
}
}
ExcelAutoshapeTest()
{
_oShape = null;
Controls.Add(txtName = new TextBox(){
Location = new Point(0,0),
Width = 150,
ReadOnly = true
});
Controls.Add(btnStartTryGet = new Button(){
Text = "Get AutoShape",
Location = new Point(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 = new TextBox(){
Location = new Point(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 = new System.Windows.Forms.Timer();
timer.Interval = 1000;
timer.Tick += (s,e)=>{
TryGetActiveAutoShape();
GC.Collect();
GC.WaitForPendingFinalizers();
};
}
void MyResize()
{
int w = ClientSize.Width;
int h = ClientSize.Height - txtContent.Top;
if(w<50){w=50;}
if(h<50){h=50;}
txtContent.Size = new Size(w,h);
}
[STAThread]
static void Main(string[] args)
{
//DumpTextOfActiveSheet();
Application.Run(new ExcelAutoshapeTest());
}
}
参考サイト
-
そもそもExcelは表計算ツールなのでオートシェイプ使う事自体がおかしなことかもしれない ↩