https://buraksenyurt.com/Burak Selim Şenyurt - Office Development2016-08-08T07:32:24+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://buraksenyurt.com/post/Word-Dosyasi-Icerisinden-Entity-FrameworkeWord Dosyası İçerisinden Entity Framework’ e2013-07-17T17:26:00+00:00bsenyurt<p><span style="color: #ff0000;"><a href="https://buraksenyurt.com/pics/275344.jpg"><img style="float: right; margin: 4px 0px; display: inline;" title="275344" src="/pics/275344_thumb.jpg" alt="275344" width="280" height="187" align="right" /></a>[Orjinal Yazım Tarihi 03-15-2013]</span></p>
<p>Merhaba Arkadaşlar,</p>
<p>Geliştirdiğimiz veya kullanmakta olduğumuz yazılım ürünlerine dahil olan, farklı segmentlerden gelen pek çok kullanıcı profili vardır. Farklı profillerin olması, bazı hallerde geliştirilmekte olan ürünlerin başarısını doğrudan etkilemektedir.</p>
<p>Bir fotoğraf işleme programını geliştirirken çoğu zaman annemizin olası kullanıcı profilleri arasına gireceğini pek düşünmeyiz. Genellikle fotoğraf işleme programını kullanacak olanların, en azından temek düzeyde fotoğrafçılık bilgisine sahip olduğunu kabul eder, menü komutlarını buna göre belirler, arayüzü buna göre hazırlarız. Ama bazı uygulamalarda annemizi hedef alır ve çektiği fotoğraflara kolayca efekt uygulamasına bir kaç basit adımda olanak tanır. Örneğin <strong>instagram</strong>’ ın <strong>iPhone </strong>uygulamasında olduğu gibi.</p>
<p>Bir yazılım geliştirme ürününü tasarlarken ise, son kullanıcının programcılar olduğunu varsayar ve arabirimin karmaşık olmasının herhangibir sorun oluşturmayacağını düşünürüz. Oysaki <strong>Team Foundation Server </strong>gibi geniş ürün yelpazesine sahip aileler düşünüldüğünde, işe dahil olan farklı profildeki kullanıcılar için işleri kolaylaştırıcı şekilde düşünüldüğüne şahit oluruz.</p>
<p>Söz gelimi proje yöneticisinin, <strong>Ms Project </strong>ürünü ile <strong>TFS</strong>’ e entegre olabildiğini, <strong>Scrum Master</strong>’ ın isterse tüm <strong>Product Backlog </strong>içeriğini bir <strong>Excel</strong> dosyasına indirip senkronize edebildiğini, <strong>Yazılım Mimarının</strong> ve <strong>Geliştiricilerin,</strong> <strong>Visual Studio </strong>ile ortama bağlanabildikleri ama birim müdürü için sadece <strong>Team Explorer</strong>’ ın kafi gelebildiğini, <strong>İş Analisti</strong> gibi geliştiriciden farklı profile sahip elemanların ise Web arayüzünü kullanarak basit bir şekilde <strong>Requirement</strong> ekleyebildikleri görürüz.</p>
<p>Sonuç olarak geliştirilen ürünün kullanım alanına dahil olan tüm personeli göz önüne alarak hareket etmemiz gerektiğinin farkında olmalıyız. İşte bu yazımızda bu konuyu tecrübe etmeye çalışacağımız bir örnek geliştiriyor olacağız. Şimdi izleyen paragraftaki senaryoyu göz önüne alalım.</p>
<h1>Senaryo</h1>
<p><strong>Selim Usta</strong> bir oto yedek parçacıdır. İşlerini kolaylaştırmak amacıyla uzun zamandır bilgisayar öğrenmeye çalışmaktadır ve en nihayetinde <strong>Word, Excel</strong> gibi ofis uygulamalarını basit seviyede de olsa kullanmaya başlamıştır. En sık yaptığı işlemlerden birisi ise stoğuna dahil ettiği yeni ürünleri bilgisayarda bir <strong>Word</strong> dosyasına kaydetmektir. Lakin zaman içerisinde <strong>Word</strong> dosyası epeyce şişmiş, içeride bir şey aramak epeyce zorlaşmıştır. Üstelik içeriğin düzgün bir formatı da yoktur.</p>
<p>Aslında ihtiyacı olan basit bir arayüz ile stoğunu takip etmektir. <strong>Rukiye</strong>, <strong>Selim Usta</strong>’ nın torunudur ve <strong>Üniversite</strong> son sınıftadır.<strong> Matematik Mühendisliği</strong> okumaktadır. Dedesinin işlerini kolaylaştırmak için bir <strong>Web</strong> arayüzü hazırlamıştır. <strong>Asp.Net MVC</strong> kullanmıştır. İyi renkler seçmiş, adımları sadeleştirmiş ve <strong>Selim Usta</strong> için kullanıcı deneyimi<em>(User Experience)</em> epeyce yüksek bir arabirim sunmuştur. Herşey yolunda gibidir. Lakin <strong>Selim Usta</strong>’ nın vazgeçemediği alışkanlıkları vardır <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_87.png" alt="Smile" /> Bir gün torununa şöyle der; <strong>“Kızım keşke şu yeni gelen tamponları bu öğrendiğim Word ile de kayıt edebilsem. Bu internet üzerinden girmek zor geliyor bana…”</strong></p>
<p>İşte şimdi bizim devreye girme sıramız. Bu yazımızda gerçekleştireceğimiz iş, <strong>bir Word dokümanının içeriğini basit bir şekilde bir veritabanına eklemek</strong> olacak. Bunun için <strong>Word</strong> üzerinde bazı <strong>Windows</strong> <strong>Form</strong> kontrollerini kullanıyor olacağız ve ayrıca kod yazarak, <strong>Entity Framework</strong> tabanlı giriş işlemleri gerçekleştireceğiz. Dilerseniz hiç vakit kaybetmeden yola koyulalım.</p>
<h1>Word Document Projesini Oluşturmak</h1>
<p><strong>Visual Studio 2012</strong> ortamımızda yeni bir <strong>Solution</strong> açarak işe başlayabiliriz. İlk projemiz <strong>Visual C#->Office/SharePoint/Office Add-ins</strong> sekmesinde yer alan <strong>Word 2010 Document</strong> tipinden olacak.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_1.png"><img style="margin: 4px 0px; display: inline;" title="wrp_1" src="/pics/wrp_1_thumb.png" alt="wrp_1" width="640" height="360" /></a></p>
<p><strong>ProductDocument</strong> olarak projeyi isimlendirdikten sonra küçük bir soru ile karşılacağız.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_2.png"><img style="margin: 4px 0px; display: inline;" title="wrp_2" src="/pics/wrp_2_thumb.png" alt="wrp_2" width="573" height="449" /></a></p>
<p>Yeni bir doküman oluşturarak ilerlemeyi tercih edelim. Ama var olan bir dokümanı da kullanabiliriz. Bu işlemlerin sonucunda <strong>Visual Studio</strong> ortamımız aşağıdaki şekle bürünecektir <img class="wlEmoticon wlEmoticon-surprisedsmile" style="border-style: none;" src="/pics/wlEmoticon-surprisedsmile_5.png" alt="Surprised smile" /></p>
<p><a href="https://buraksenyurt.com/pics/wrp_3.png"><img style="margin: 4px 0px; display: inline;" title="wrp_3" src="/pics/wrp_3_thumb.png" alt="wrp_3" width="640" height="440" /></a></p>
<p>Dikkat edileceği üzere <strong>IDE</strong>’ nin göbeğinde <strong>docx</strong> uzantılı bir <strong>Word</strong> belgesi yer almaktadır. Hatta <strong>Solution Explorer</strong> penceresine baktığımızda, <strong>ThisDocument.cs</strong> isimli bir sınıf dosyası olduğunu, <strong>Toolbox</strong> içerisinde ise pek çok <strong>Form</strong> kontrolünün yer aldığını görürüz <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_184.png" alt="Winking smile" /> Bu, kısaca şu anlama gelmektedir; <strong>Word Object Model</strong>’ in üzerine <strong>Windows Form</strong> kontrollerini ekleyebilir ve <strong>C#</strong> ile kodlama yapabiliriz. Öyleyse <strong>Selim Usta</strong> için basit bir içerik hazırlayarak ilerleyelim<em>(Word Object Model ile ilişkili olarak <a href="http://msdn.microsoft.com/en-us/library/vstudio/kw65a0we.aspx" target="_blank">bu adresten daha detaylı bilgi</a> tedarik edebilirsiniz)</em></p>
<h1>Word Tasarımını Yapalım</h1>
<p><strong>Word</strong> belgesini <strong>Ribon</strong> tarafında yer alan bileşenler ile donatabileceğimiz gibi <strong>Toolbox </strong>üzerinde yer alan <strong>Component</strong>’ leri içermesini de sağlayabiliriz. Bu anlamda melez bir arayüz geliştirme ortamı oluştuğunu ifade edebiliriz. Hem <strong>Word</strong> hem de <strong>Windows Forms</strong> kontrollerini bir arada ele alabilmekteyiz. Bu düşünceler ışığında <strong>Selim Usta</strong> için aşağıdaki formu oluşturduğumuzu düşünelim.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_4.png"><img style="margin: 4px 0px; display: inline;" title="wrp_4" src="/pics/wrp_4_thumb.png" alt="wrp_4" width="635" height="688" /></a></p>
<p>Dikkat edileceği üzere <strong>Word</strong> içeriğine <strong>TextBox, DateTimePicker, NumericUpDown, Button</strong> kontrolleri eklenmiştir. Kontrollere kod tarafı için anlamlı isimler vererek ilerleyelim. Ben örnekte <strong>[KontrolTipi][TabloKolonAdı]</strong> şeklinde bir notasyon kullandım. Yani <strong>Name</strong> alanı için <strong>TextBoxName</strong>, açıklama alanı için <strong>TextBoxDescription</strong> vb…</p>
<h1>Entity Framework Çözümünün Eklenmesi</h1>
<p><strong>Solution</strong> içerisinde <strong>Entity Framework</strong> tabanlı bir <strong>Class</strong> <strong>Library</strong> projesi de yer almaktadır. Söz konusu proje bir <strong>Ado.Net Entity Model</strong> öğesi bulundurmakta olup aşağıdaki diagramda görülen içeriğe sahiptir.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_5.png"><img style="margin: 4px 0px; display: inline;" title="wrp_5" src="/pics/wrp_5_thumb.png" alt="wrp_5" width="410" height="550" /></a></p>
<p><strong>Product</strong> <strong>Entity</strong> tipi, <strong>Depomuz</strong> isimli <strong>SQL 2008</strong> veritabanında yer alan <strong>Product</strong> tablosunu işaret etmektedir. Otomatik artan ve <strong>Primary Key</strong> olan <strong>ProductId</strong> alanı dışında, <strong>Name</strong>(nvarchar(50)), <strong>Description</strong>(nvarchar(250)), <strong>ListPrice</strong>(decimal(18,0)), <strong>RealPrice</strong>(decimal(18,0)), <strong>InsertDate</strong>(Date), <strong>Quantity</strong>(int) ve <strong>Notes</strong>(nvarchar(250)) gibi kolonları da içermektedir.</p>
<p>Pek tabi bir <strong>Word</strong> dokümanından <strong>C#</strong> kodlarını kullanarak farklı bir kütüphaneye erişebildiğimize göre, <strong>WCF</strong> servislerini de çağırmamız mümkündür. Özellikle bir şirketin bu tip bir dokümanı kullanarak, çeşitli <strong>Repository</strong>’ lere kayıt atması istenen durumlarda, bir <strong>Servis</strong> kanalına uğranmasını sağlamak yerinde bir davranış olabilir. <em>(Dolayısıyla senaryonuzu, <strong>Entity Framework</strong> kütüphanesi ile <strong>Word</strong> projesi arasına bir<strong> WCF Servisi</strong> sokarak genişletebilirsiniz)</em></p>
<h1>Kodlar</h1>
<p>Tabiki ilk etapta <strong>Word</strong> projesinin, <strong>Entity Library</strong> kütüphanesini referans etmesi gerekmektedir.</p>
<blockquote>
<p>Burada dikkat edilmesi gereken noktalardan birisi de Target Framework seçimidir. Oluşturduğumuz Word Document projesi .Net Framework 4.0 odaklıdır. Bu sebeple Entity Framework tabanlı olan Class Library projesinin de .Net Framework 4.0 odaklı olması gerekmektedir. Aksi durumda Target Framework uyuşmazlığı oluşuacak ve Word Document tipi projeye eklenen referans için bir Warning alınacaktır.</p>
</blockquote>
<p>Kod yazımı işin eğlenceli taraflarından birisidir elbette <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_184.png" alt="Winking smile" /> <strong>Word</strong> projesindeki <strong>docx</strong> dosyası, bir de <strong>C#</strong> kod dosyası içermektedir. Burada <strong>Word</strong>’ ün <strong>Object Model</strong>’ ine <strong>this</strong> anahtar kelimesi üzerinden kolayca erişilebilinir. Daha da önemlisi bazı olaylar<em>(Events)</em> yüklenerek dokümanının davranışları fonksiyonel olarak değiştirilebilir. Örneğin bu <strong>Word</strong> dokümanı kayıt edilmeden önce veya sonra devreye girecek<strong> olay metodları<em>(Event Handlers) </em></strong>dahil edilebilir. Dolayısıyla yapabileceklerimiz oldukça geniş bir yelpazeye yayılmaktadır. Biz örneğimizde oldukça basit ilerledik ve aşağıdaki kod yapısını oluşturduk.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using AzonEntityLibrary;
using System;
using System.Windows.Forms;
using Word = Microsoft.Office.Interop.Word;
namespace ProductDocument
{
public partial class ThisDocument
{
private void ThisDocument_Startup(object sender, System.EventArgs e)
{
this.Application.DocumentBeforeSave += Application_DocumentBeforeSave;
}
private void ThisDocument_Shutdown(object sender, System.EventArgs e)
{
}
void Application_DocumentBeforeSave(Word.Document Doc, ref bool SaveAsUI, ref bool Cancel)
{
SaveToDatabase();
}
private bool SaveToDatabase()
{
bool result = false;
try
{
using (DepomuzEntities context = new DepomuzEntities())
{
Product newProduct = new Product
{
Name = TextBoxName.Text,
Description = TextBoxDescription.Text,
InsertDate = DateTimePickerEnterDate.Value,
ListPrice = System.Convert.ToDecimal(TextBoxListPrice.Text),
RealPrice = System.Convert.ToDecimal(TextBoxRealPrice.Text),
Quantity = System.Convert.ToInt32(NumericUpDownQuantity.Value),
Notes = TextBoxNotes.Text
};
context.Products.Add(newProduct);
context.SaveChanges();
result = true;
MessageBox.Show(
string.Format("Selim Ustam ürün {0} numarası ile dosyalandı"
,newProduct.ProductId.ToString()));
}
}
catch(Exception excp)
{
MessageBox.Show("Selim Ustam beni arar mısın? Sanırım işlemin sırasında bir hata oluştu");
//TODO@Rukiye burada oluşan istisnaları kendime mail atayım ve hatta log dosyasına yazdırayım
}
return result;
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
SaveToDatabase();
}
#region VSTO Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.ButtonAdd.Click += new System.EventHandler(this.ButtonAdd_Click);
this.Startup += new System.EventHandler(this.ThisDocument_Startup);
this.Shutdown += new System.EventHandler(this.ThisDocument_Shutdown);
}
#endregion
}
}</pre>
<p>Kod dosyasında dikkat çeken noktalardan birisi default olarak üretilen olay metodlarıdır. <strong>ThisDocument_Startup</strong> ve <strong>ThisDocument_Shutdown</strong>. Bu olay metodları Word dokümanı başlatılırken ve kapatılırken devreye girmektedir. Örnekte, <strong>ThisDocument_Startup</strong> fonksiyonunda, <strong>DocumentBeforeSave</strong> olay metodunun yüklenmesi işlemi yapılmıştır.</p>
<p>Yeni bir ürünün <strong>Entity Framework</strong> üzerinden veritabanına kayıt edilmesi işlemi iki farklı noktadan tetiklenmektedir. Birincisi, <strong>Word</strong> dokümanının <strong>Save</strong> komutu verildikten ama <strong>Save</strong> operasyonu tamamlanmadan öncedir. Bunun için dikkat edileceği üzere <strong>Application</strong> referansı üzerinden <strong>DocumentBeforeSave</strong> olay metodu yüklenmiştir. İkinci tetikleme noktamız ise <strong>Word</strong> dokümanı üstüne atılmış olan <strong>Button</strong> kontrolünün <strong>Click</strong> olay metodudur. Yani, bir <strong>Word</strong> dokümanının var olan <strong>Object Model’</strong> ine ait olay metodlarından yararlanılabileceği gibi, doküman üzerine bırakılmış <strong>Windows Form</strong> kontrollerinin olay metodlarından da yararlanılabilinir.</p>
<p><strong>SaveToDatabase</strong> metodu içerisinde <strong>Context</strong> nesnesi kullanılmaktadır. <strong>Word</strong> dokümanı üzerindeki kontrollere ait bilgiler yeni üretilen <strong>Product</strong> nesne örneğinin özelliklerine set edildikten sonras ise kayıt altına alma işlemi yapılmaktadır. Yeni <strong>Product</strong> örneği, <strong>Products</strong> özelliği üzerinden <strong>Add</strong> metodu ile <strong>generic DbSet</strong>’ e ilave edildikten sonra <strong>SaveChanges</strong> çağrısı ile de veritabanına yazılmaktadır.</p>
<h1>Kaba Testler</h1>
<p>Uygulamayı <strong>F5</strong> ile çalıştırdığımızda ve örnek bazı veriler girdiğimizde kayıt işleminin başarılı bir şekilde gerçekleştirildiğine dair bir mesaj kutusu ile karşılaşırız. Aynen aşağıdaki ekran görüntüsündeki gibi.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_6.png"><img style="margin: 4px 0px; display: inline;" title="wrp_6" src="/pics/wrp_6_thumb.png" alt="wrp_6" width="632" height="765" /></a></p>
<p>Ki eklenme işleminin başarılı olup olmadığını hemen veritabanına bakarak öğrenebiliriz.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_8.png"><img style="margin: 4px 0px; display: inline;" title="wrp_8" src="/pics/wrp_8_thumb.png" alt="wrp_8" width="640" height="50" /></a></p>
<p>Eğer ters bir durum oluşursa<em>(örneğin form boş iken Save etmeye çalışmak gibi)</em>, bu durumda bir çalışma zamanı hatası alınacak ama durum <strong>Selim Usta</strong>’ ya yumuşatılarak iletilecektir <img class="wlEmoticon wlEmoticon-laughingoutloud" style="border-style: none;" src="/pics/wlEmoticon-laughingoutloud_8.png" alt="Laughing out loud" /></p>
<p><a href="https://buraksenyurt.com/pics/wrp_7.png"><img style="margin: 4px 0px; display: inline;" title="wrp_7" src="/pics/wrp_7_thumb.png" alt="wrp_7" width="628" height="424" /></a></p>
<h1>Build Sonrası</h1>
<p>Aslında uygulamanın Build sonrası durumuna baktığımızda aşağıdaki şekilde görülen içeriğin üretildiğini fark edebiliriz.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_9.png"><img style="margin: 4px 0px; display: inline;" title="wrp_9" src="/pics/wrp_9_thumb.png" alt="wrp_9" width="263" height="343" /></a></p>
<p><strong>Word Document</strong> projesi,<strong> ProductDocument.docx</strong> haricinde, <strong>Solution</strong> da kullanılan başka dosyaları da doğal olarak içerecektir. Tabi burada akla gelen ilk soru bu içeriği nasıl dağıtılabileceğidir? <strong>Development</strong> yapılan makinede herhangibir sorun olmayacaktır. <strong>Debug</strong> veya <strong>Release</strong> klasöründeki <strong>ProductDocument.dox</strong> dosyasının çalıştırılması yeterlidir. Ancak bu çözümü <strong>Selim Usta</strong>’ nın bilgisayarına yüklemek için en azından bir <strong>Setup</strong> paketine sahip olmak dağıtım işini kolaylaştıracaktır.</p>
<p>Bunun için <strong>Publish</strong> işlemi <strong>Word Document</strong> projesi için uygulanabilir. Burada <strong>Click Once</strong> teknolojisinden yararlanılabildiğini de belirtelim. Bir <strong>Publish</strong> paketini söz konusu uygulama için nasıl hazırlayabileceğinizi <a href="http://msdn.microsoft.com/en-us/library/vstudio/bb772100.aspx" target="_blank">MSDN üzerindeki bu adresten öğrenebilirsiniz</a>. Detayları ayrı bir makale konusu olacağından burada derinlemesine incelemedik.</p>
<blockquote>
<p>İlgili adresteki içeriği dikkatlice okumanızı ve özellikle Post-Deployment kullanımına bakmanızı öneririm. Nitekim Post-Deployment sırasında, ilgili Word dosyasının bir kopyasının istemci bilgisayarda istenen bir klasöre atanması işlemi gerçekleştirilebilmektedir. Ayrıca Publisher’ ın Trusted olarak kabul edilebilmesi için gerekli Signing işlemlerini de atlamayın derim <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_184.png" alt="Winking smile" /> </p>
</blockquote>
<p><strong>Publish</strong> işlemi sonrası aşağıdaki ekran görüntüsündekine benzer bir içerik oluşacaktır. Setup dosyasını kullanarak tipik bir install işlemi gerçekleştirebilirsiniz. Ayrıca bu klasörde yer alan <strong>ProductDocument</strong> çalıştırıldığında doğrudan tasarlamış olduğumuz <strong>Form</strong>’ un açıldığını görebiliriz.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_10.png"><img style="margin: 4px 0px; display: inline;" title="wrp_10" src="/pics/wrp_10_thumb.png" alt="wrp_10" width="436" height="178" /></a></p>
<h1>Sonuç</h1>
<p>Geliştirdiğimiz örnek aslında <strong>Document Level</strong> tipinden kabul edilen bir proje uygulamasıdır. İstenirse <strong>Application Level</strong> şeklinde bir proje de üretilebilir ki bu durumda tüm <strong>Word</strong> dokümanları için uygulama seviyesinde bir geliştirme yapma şansına sahip olabiliriz. Elbette yazımıza konu olan ve <strong>Selim Usta</strong>’ nın işine yarayacağını düşündüğümüz çözümün geliştirilmesi gereken pek çok yeri vardır. Örneğin,</p>
<ul>
<li>Form üzerinde bir <strong>doğrulama<em>(Validation)</em></strong> mekanizması mevcut değildir. Çok doğal olarak Selim Usta sayısal olması gereken alanlara metinsel içerik girebilir.</li>
<li><strong>Word</strong> dosyası üzerinden yeni bir ürün eklendiğinde belki form temizlenebilir ve hatta belki de alt sayfalarda yer alan bir <strong>DataGridView</strong> kontrolü içerisine, yapılan ekler basılarak özet bir durum raporu sunulabilir.</li>
<li><strong>Selim Usta</strong> dalgınlıkla yanlış bir içerik girebilir. Bu durumda ilgili kayıtları silmek isteyecektir. Bu vakanın da doküman yoluyla karşılanması gerekebilir. Ya da mevzunun Rukiye’ ye iletilmesi yolu tercih edilebilir <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_87.png" alt="Smile" /></li>
<li>Bir <strong>WCF</strong> servis katmanının olması da çok daha iyi olabilir. Nitekim bu sayede <strong>Word Document</strong> projesini kullanan herhangibir istemci bilgisayarının sadece servise ulaşması yeterli olacaktır. Ki servis de Host edildiği makinede <strong>Entity Framework’</strong> ü kullanarak bir<strong> Repository’</strong> ye yazma işlemini icra edebilir ve bu sayede <strong>Word</strong> dosyasının olduğu bilgisayar için <strong>Loosely Coupled</strong> bir geçerlilik de sağlanmış olur. </li>
</ul>
<p>Bu ve benzeri eksiklikleri siz değerli okurlarıma bırakıyorum. Diğer yandan senaryoyu biraz daha farklılaştırabilirsiniz. Söz gelimi <strong>TFS Client Object Model</strong>’ i de işin içerisine katabilir ve bir <strong>Word</strong> <strong>Template</strong>’ i üzerinden <strong>Product Backlog Item</strong> ve <strong>Task</strong> girişlerini yaptırabilirsiniz. Bu ödev için aşağıdaki grafiği göz önüne alabilirsiniz.</p>
<p><a href="https://buraksenyurt.com/pics/wrp_11.png"><img style="margin: 4px 0px; display: inline;" title="wrp_11" src="/pics/wrp_11_thumb.png" alt="wrp_11" width="573" height="454" /></a></p>
<p>Böylece geldik bir yazımızın daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_184.png" alt="Winking smile" /></p>
<p><a href="https://buraksenyurt.com/pics/2013%2f2%2fHowTo_Word.zip">HowTo_Word.zip (1,80 mb)</a> <br /><span style="color: #ff0000;">[Dosya boyutunun küçülmesi için Packages ve Release klasörleri silinmiştir]</span></p>
<p><span style="color: #ff0000;">[Orjinal Yazım Tarihi 03-15-2013]</span></p>2013-07-17T17:26:00+00:00office developmentword projectsmicrosoft wordofficeword addinaddinvisual studio 2012.netc#entity frameworkdocument levelapplication levelword object modelbsenyurtGeliştirdiğimiz veya kullanmakta olduğumuz yazılım ürünlerine dahil olan, farklı segmentlerden gelen pek çok kullanıcı profili vardır. Farklı profillerin olması, bazı hallerde geliştirilmekte olan ürünlerin başarısını doğrudan etkilemektedir. Bir fotoğraf işleme programını geliştirirken çoğu zaman annemizin olası kullanıcı profilleri arasına gireceğini pek düşünmeyiz. Genellikle fotoğraf işleme programını kullanacak olanların, en azından temek düzeyde fotoğrafçılık bilgisine sahip olduğunu kabul eder, menü komutlarını buna göre belirler, arayüzü buna göre hazırlarız. Ama bazı uygulamalarda annemizi hedef alır ve çektiği fotoğraflara kolayca efekt uygulamasına bir kaç basit adımda olanak tanır. Örneğin instagram’ ın iPhone uygulamasında olduğu gibi.https://buraksenyurt.com/pingback.axdhttps://buraksenyurt.com/post.aspx?id=e29ba705-e46f-455e-ae0f-6ae1592901306https://buraksenyurt.com/trackback.axd?id=e29ba705-e46f-455e-ae0f-6ae159290130https://buraksenyurt.com/post/Word-Dosyasi-Icerisinden-Entity-Frameworke#commenthttps://buraksenyurt.com/syndication.axd?post=e29ba705-e46f-455e-ae0f-6ae159290130https://buraksenyurt.com/post/Excel-ve-Entity-Framework-KonusuyorExcel ve Entity Framework Konuşuyor2013-06-30T17:57:00+00:00bsenyurt<p><a href="https://buraksenyurt.com/pics/handshake.jpg"><img style="float: right; margin: 4px 0px; display: inline;" title="handshake" src="/pics/handshake_thumb.jpg" alt="handshake" width="280" height="198" align="right" /></a><span style="color: #ff0000;">[Orjinal Yazım Tarihi 03-05-2013]</span></p>
<p>Merhaba Arkadaşlar,</p>
<p>Artık uygulamaların birbirleri ile konuşmaları çok ama çok kolay. Bu gerçekten önemli bir mesele. Özellikle farklı segmentlerden insanların bir araya geldiği bilişim toplumlarında. Kimi kullanıcı için <strong>Office Excel, Word</strong> veya <strong>Powerpoint</strong> çok şey ifade ederken, kimi kullanıcı içinde<strong> SQL Management Studio</strong> ortamında hazırlanan karmaşık bir sorguya bakmak daha anlamlı olabiliyor. Ya da bir <strong>Web</strong> sayfası üzerinden alınan raporlar şirketin <strong>Muhasebe Şefi</strong> için değerli iken, kimisi <strong>SSRS </strong>ile elde edilen raporları mobil cihazında görmeyi tercih edebiliyor.</p>
<p>Ancak <strong>Developer</strong> gözüyle olaya bakıldığında, her segmenti memnun edecek şekilde geliştirme yapması beklendiği oldukça aşikar. Bu sebepten, farklı uygulamaların birbirleriyle rahatça konuşabilmeleri önemli bir mesele olarak karşımıza çıkıyor. <strong>Visual Studio 2012</strong> tarafında olaya baktığımızda bir <strong>Office</strong> uygulamasının, önceki sürümlere göre <strong>.Net Framework</strong> ile daha yüksek seviyede etkileşime girerek tasarlanabilmesi/geliştirilebilmesi de pekala mümkün.</p>
<p>Özellikle <strong>Sheet</strong>’ ler veya <strong>Workbook</strong>’ lar kodlanabilir birer <strong>C#(</strong><strong>Vb.Net)</strong> dosyası olduğu için, uygulama bazında istediğimiz taklayı atma şansına sahibiz. İşte bu düşünceler ışığında yola çıktığımız ve okumakta olduğunuz yazımızda, <strong>Excel</strong>’ i, <strong>Entity Framework’</strong> ü, <strong>C#</strong>’ ı işin içerisine katacak ve birbirleri ile konuşmalarını sağlamaya çalışacağız. Haydi hiç vakit kaybetmeden yola koyulalım. Ama önce örnek senaryomuz <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_193.png" alt="Winking smile" /></p>
<h1>Senaryo</h1>
<p>Amacımız, <strong>Northwind</strong> veritabanında bulunan 3 adet <strong>View</strong> nesne örneğinin <strong>Excel</strong> dokümanı içerisindeki <strong>Sheet’</strong> ler de gösterilmesini sağlamak. Bu amaçla <strong>Category Sales for 1997</strong>, <strong>Product Sales for 1997</strong> ve <strong>Invoices</strong> isimli <strong>View</strong> nesnelerini kullanıyor olacağız. <strong>Sheet1</strong> içeriğini kendi kod dosyası içerisinde üretmek istiyoruz. <strong>Sheet2</strong> ve <strong>Sheet3</strong> içeriklerini ise, <strong>Workbook</strong>’ a ait kod dosyasından besliyor olacağız. Bu noktada ağırlıklı olarak <strong>Workbook</strong> ve <strong>Sheet</strong> sınıflarının ilgili başlangıç noktalarını değerlendireceğiz. Kabaca senaryomuzu işaret eden aşağıdaki görseli göz önüne alabiliriz.</p>
<p><a href="https://buraksenyurt.com/pics/ewef_8.png"><img style="margin: 4px 0px; display: inline;" title="ewef_8" src="/pics/ewef_8_thumb.png" alt="ewef_8" width="577" height="453" /></a></p>
<h1>Konuşan Çözüm</h1>
<p>Dilerseniz senaryo içerisinde tarafların gözünden olaya bakalım.</p>
<h2>Sheet Konuşuyor</h2>
<p>"Merhaba, benim adım <strong>Sheet1</strong>. Çalıştırıldığımda <strong>Sheet1_Startup</strong> olay metoduna bir çağrıda bulunurum. Ey Startup metodu, haydi işini yap derim. O da kendi içinde<strong> Entity Framework</strong> tabanlı <strong>Context</strong> nesnesini kullanır ve <strong>1997</strong> yılına ait kategori bazlı satışların verilerini, sahip olduğum hücrelere teker teker aktarır<img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_93.png" alt="Smile" /> Onunla çok iyi anlaşırız.</p>
<h2>Workbook Konuşuyor</h2>
<p>Merhaba, ben <strong>ThisWorkbook</strong>. Ben sahip olduğum tüm <strong>Sheet</strong>’ leri yönetebilirim. Örneğin kendi <strong>Startup</strong> metoduma, tüm <strong>Sheet</strong>’ leri çeşitli yerlerden topladığı veriler ile doldurmasını söyleyebilirim. <strong>He-Man</strong> ile aramdaki tek fark onun kılıcının olmasıdır.</p>
<h1>Hazırlıklar</h1>
<p>Dilerseniz senaryomuzu nihai sonuca ulaştırmak için adım adım ilerlemeye başlayalım. İlk olarak <strong>Visual Studio 2012</strong> ortamında bir <strong>Excel 2010 Workbook</strong> projesi oluşturmalıyız. Bu nedenle <strong>New Project</strong> kısmında ilgili proje tipini işaretliyoruz.</p>
<p><a href="https://buraksenyurt.com/pics/ewef_7.png"><img style="margin: 4px 0px; display: inline;" title="ewef_7" src="/pics/ewef_7_thumb.png" alt="ewef_7" width="473" height="307" /></a></p>
<p>Bu işlemin ardından <strong>Northwind</strong> veritabanına ait <strong>Entity</strong> içeriğini barındıracak bir <strong>Class</strong> <strong>Library</strong> projesini aynı <strong>Solution</strong> içerisine ekleyebilir ve aşağıdaki gibi mevzuya konu olan <strong>View</strong> nesnelerini içeren <strong>Entity Data Model </strong>öğesini üretebiliriz.</p>
<p><a href="https://buraksenyurt.com/pics/ewef_1.png"><img style="margin: 4px 0px; display: inline;" title="ewef_1" src="/pics/ewef_1_thumb.png" alt="ewef_1" width="543" height="516" /></a></p>
<p>Çok doğal olarak <strong>Excel</strong> uygulamasının, söz konusu <strong>Class Library</strong>’ yi ve ayrıca <strong>EntityFramework</strong> <strong>Assembly</strong>’ ını referans etmesi gerekmektedir. <strong>Solution </strong>içeriği şu an itibariyle aşağıdaki gibi olacaktır.</p>
<p><a href="https://buraksenyurt.com/pics/ewef_2.png"><img style="margin: 4px 0px; display: inline;" title="ewef_2" src="/pics/ewef_2_thumb.png" alt="ewef_2" width="284" height="312" /></a></p>
<p>Dikkat edileceği üzere <strong>HowTo_ExcelWithEF</strong> uygulaması içerisinde <strong>Workbook</strong> ve söz konusu <strong>Workbook’</strong> a ait <strong>Sheet</strong>’ ler için birer kod dosyası bulunmaktadır. Bu kod dosyaları içerisindeki pek çok olay metoduna müdahale edebilir ve çalışma zamanını kontrol altına alabiliriz ki örneğimizde de benzer bir işi gerçekleştiriyor olacağız.</p>
<p>Kritik noktalardan birisi de, <strong>Entity</strong> kütüphanesini kullanacak çalıştırılabilir uygulamanın, <strong>Connection</strong> <strong>String</strong> bilgisine sahip olması zorunluluğudur. Bu nedenle <strong>NorthwindLibrary</strong> içerisindeki <strong>App.Config</strong> dosyasına ait <strong>Connection</strong> <strong>String</strong> bilgisini, <strong>HowTo_ExcelWithEF</strong> uygulamasında da kullanmalıyız.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="NorthwindEntities" connectionString="metadata=res://*/NorthwindModel.csdl|res://*/NorthwindModel.ssdl| res://*/NorthwindModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=Northwind;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration></pre>
<p>Artık kodlama tarafını tamamlayabiliriz. İlk olarak <strong>Sheet1.cs</strong> içeriğini aşağıdaki gibi geliştirdiğimizi düşünelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using NorthwindLibrary;
using System.Linq;
namespace HowTo_ExcelWithEF
{
public partial class Sheet1
{
private void Sheet1_Startup(object sender, System.EventArgs e)
{
using(NorthwindEntities context=new NorthwindEntities())
{
var categoryBasedSales = from s in context.Category_Sales_for_1997
orderby s.CategorySales descending
select new {
s.CategoryName, s.CategorySales
};
int rowIndex = 1;
Cells[rowIndex, 1] = "Kategori";
Cells[rowIndex, 2]= "Satışlar";
Cells[rowIndex, 1].Font.Bold = true;
Cells[rowIndex, 2].Font.Bold = true;
foreach (var sale in categoryBasedSales)
{
rowIndex++;
Cells[rowIndex, 1]= sale.CategoryName;
Cells[rowIndex, 2]= sale.CategorySales;
}
}
}
private void Sheet1_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(Sheet1_Startup);
this.Shutdown += new System.EventHandler(Sheet1_Shutdown);
}
#endregion
}
}</pre>
<p><strong>Startup</strong> metodunda <strong>context</strong> nesne örneği kullanılarak ilgili <strong>View</strong>’ dan <strong>Anonymous </strong>tipte bir nesne listesi oluşturulmaktadır. Söz konusu liste <strong>Sheet1</strong> içerisindeki hücrelere yerleştirilir. Bunun için <strong>Cells[rowIndex,columnIndex]</strong> ifadesi ele alınmaktadır. Kodu yazarken dikkat edilecek olursa <strong>dynamic</strong> özelliğinin kullanılmakta olduğu görülebilir. Yani noktadan sonrasındaki atamalar ve bunlara ait tipler çalışma zamanında çözümlenecektir. Bu biraz performans kaybına yol açacak olsa da şu anki senaryodaki gibi küçük veri kümelerinde önemsizdir.</p>
<p><a href="https://buraksenyurt.com/pics/ewef_9.png"><img style="margin: 4px 0px; display: inline;" title="ewef_9" src="/pics/ewef_9_thumb.png" alt="ewef_9" width="630" height="76" /></a></p>
<p><strong>1,1</strong> ve <strong>1,2</strong> hücrelerini başlıklar ile doldurduktan sonra<em>(Excel tarafında ilk hücre satır sütun değeri 0,0 değil 1,1 dir)</em> bunların <strong>Bold</strong> olması sağlanmıştır. Diğer yandan sonuç listesi üzerinde dönülmekte ve diğer hücreler, <strong>View</strong> dan gelen veriler ile beslenmektedir. Bu kodlamaya göre veri <strong>Sheet1</strong>’ in kod dosyası da doldurulmaktadır. Pek tabi <strong>Sheet</strong>’ lerin <strong>Workbook</strong>’ a ait olay metodlarında şekillendirilmesi de söz konusudur. <strong>Sheet2</strong> ve <strong>Sheet3</strong> bu amaçla <strong>Workbook.cs</strong> içerisinde ele alınmıştır. Aynen aşağıdaki kod parçasında görüldüğü gibi.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using NorthwindLibrary;
using System.Drawing;
using System.Linq;
namespace HowTo_ExcelWithEF
{
public partial class ThisWorkbook
{
private void ThisWorkbook_Startup(object sender, System.EventArgs e)
{
using(NorthwindEntities context=new NorthwindEntities())
{
#region Entity View içeriklerinin çekilmesi
var invoices = from i in context.Invoices
orderby i.CustomerName
select new
{
From = i.Country + "," + i.City,
i.CustomerID,
i.CustomerName,
i.OrderDate,
ShipTo = i.ShipCountry + "," + i.ShipCity
};
var prdoductSalesFor1997 = from s in context.Product_Sales_for_1997
orderby s.ProductSales descending
,s.CategoryName ascending
,s.ProductName ascending
select new
{
Product=s.CategoryName+"-"+s.ProductName,
s.ProductSales
};
#endregion
#region Sheet2 nin Invoices içeriği ile doldurulması
int rowIndex = 1;
Sheets["sheet2"].Cells[rowIndex, 1] = "From";
Sheets["sheet2"].Cells[rowIndex, 1].Font.Bold = true;
Sheets["sheet2"].Cells[rowIndex, 2] = "Customer ID";
Sheets["sheet2"].Cells[rowIndex, 2].Font.Bold = true;
Sheets["sheet2"].Cells[rowIndex, 3] = "Customer";
Sheets["sheet2"].Cells[rowIndex, 3].Font.Bold = true;
Sheets["sheet2"].Cells[rowIndex, 4] = "Order Date";
Sheets["sheet2"].Cells[rowIndex, 4].Font.Bold = true;
Sheets["sheet2"].Cells[rowIndex, 5] = "Ship To";
Sheets["sheet2"].Cells[rowIndex, 5].Font.Bold = true;
foreach (var invoice in invoices)
{
rowIndex++;
Sheets["sheet2"].Cells[rowIndex, 1] = invoice.From;
Sheets["sheet2"].Cells[rowIndex, 2] = invoice.CustomerID;
Sheets["sheet2"].Cells[rowIndex, 3] = invoice.CustomerName;
Sheets["sheet2"].Cells[rowIndex, 4] = invoice.OrderDate;
Sheets["sheet2"].Cells[rowIndex, 5] = invoice.ShipTo;
}
#endregion Sheet2 nin Invoices içeriği ile doldurulması
#region Sheet3 ün 1997 yılına ait satış verileri ile doldurulması
rowIndex = 1;
Sheets["sheet3"].Cells[rowIndex, 1] = "Product";
Sheets["sheet3"].Cells[rowIndex, 1].Font.Bold = true;
Sheets["sheet3"].Cells[rowIndex, 2] = "Sales";
Sheets["sheet3"].Cells[rowIndex, 2].Font.Bold = true;
foreach (var sales in prdoductSalesFor1997)
{
rowIndex++;
Sheets["sheet3"].Cells[rowIndex, 1] = sales.Product;
if (sales.ProductSales > 30000)
{
Sheets["sheet3"].Cells[rowIndex, 2].Interior.Color = Color.Black;
Sheets["sheet3"].Cells[rowIndex, 1].Interior.Color = Color.Black;
Sheets["sheet3"].Cells[rowIndex, 2].Font.Color = Color.Gold;
Sheets["sheet3"].Cells[rowIndex, 1].Font.Color = Color.Gold;
}
Sheets["sheet3"].Cells[rowIndex, 2] = sales.ProductSales;
}
#endregion Sheet3 ün 1997 yılına ait satış verileri ile doldurulması
}
}
private void ThisWorkbook_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisWorkbook_Startup);
this.Shutdown += new System.EventHandler(ThisWorkbook_Shutdown);
}
#endregion
}
}</pre>
<blockquote>
<p>Office uygulamalarını geliştirirken C# 4.0 ile birlikte gelen dynamic, Optional and Named Parameters gibi yeniliklerin işlerimizi nasıl kolaylaştırdığına bir kere daha şahit oluyoruz.</p>
</blockquote>
<p>Kodlarda bizi zorlayacak bir karmaşa yoktur. İki <strong>View</strong> sırasıyla sorgulanmakta ve elde edilen listeler ilgili <strong>Sheet</strong>’ ler deki hücrelere satır satır doldurulmaktadır. Özellikle <strong>1997 yılına ait satış rakamları</strong> alınırken <strong>30000 </strong>birimden büyük olunması halinde, o satırın arka plan ve font renkleri değiştirilerek göze batmaları sağlanmaktadır <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_93.png" alt="Smile" /> Dikkate değer noktalar, ilgili hücrelerin nasıl formatlandığı veya belirli bir <strong>Sheet</strong>’ e nasıl ulaşıldığı ile alakalıdır.</p>
<h1>Sonuçlar</h1>
<p>Uygulamayı çalıştırdığımızda çalışma zamanında bir <strong>Excel Workbook</strong>’ un açıldığını ve <strong>Sheet1, Sheet2, Sheet3</strong> sayfalarının ilgili <strong>View</strong> içerikleri ile doldurulduğunu görebiliriz.</p>
<p><em>Sheet1 içeriği kategori bazlı satış verilerl ile</em></p>
<p><a href="https://buraksenyurt.com/pics/ewef_3.png"><img style="margin: 4px 0px; display: inline;" title="ewef_3" src="/pics/ewef_3_thumb.png" alt="ewef_3" width="373" height="442" /></a></p>
<p><em>Sheet 2 içeriği Müşteri faturalarıyla,</em></p>
<p><a href="https://buraksenyurt.com/pics/ewef_4.png"><img style="display: inline;" title="ewef_4" src="/pics/ewef_4_thumb.png" alt="ewef_4" width="537" height="442" /></a></p>
<p><em>son olarak Sheet3 içeriği de ürün bazlı satış rakamlarıyla doldurulacaktır.</em></p>
<p><a href="https://buraksenyurt.com/pics/ewef_5.png"><img style="margin: 4px 0px; display: inline;" title="ewef_5" src="/pics/ewef_5_thumb.png" alt="ewef_5" width="392" height="442" /></a></p>
<p>Görüldüğü üzere bir <strong>Excel</strong> içeriğini <strong>Entity Framework</strong> üzerinden geçerek veri ile doldurmak son derece kolaydır. Elbette gerçek hayat senaryoları düşünüldüğünde, ilgili veri içeriğinin asenkron olarak ve hatta servisler yardımıyla doldurulması daha doğru bir yaklaşım olacaktır. Zaten <strong>Excel</strong>’ in konuşabildiği pek çok dış dünya aracı servis bazlı veri sunmaktadır<em>(OData servislerinden veri çekilmesi ve Excel içerisinde Pivot table olarak gösterilebilmesi konusunu araştırabilirsiniz)</em></p>
<p>Tamamlanan uygulamanın herhangibir bilgisayarda veya ortamda çalıştırılabilmesi için aşağıdaki görselde yer alan içeriğin taşınması yeterli olacaktır. Elbette veritabanı bağlantısının olduğunu ve ilgili <strong>Northwind</strong> içeriklerine ulaşılabildiğini varsayıyoruz.</p>
<p><a href="https://buraksenyurt.com/pics/ewef_6.png"><img style="margin: 4px 0px; display: inline;" title="ewef_6" src="/pics/ewef_6_thumb.png" alt="ewef_6" width="263" height="228" /></a></p>
<p>Böylece geldik bir yazımızın daha sonuna. Size düşen örneği daha da zengilenştirmektir. Örneğin,</p>
<ul>
<li>n sayıda Sheet’ in doldurulması noktasında <strong>asenkron</strong> bir işleyişin ele alınmasını sağlayabilirsiniz.</li>
<li>Aynı uygulamayı <strong>Office 2013</strong> standartlarında ele alıp, <strong>.Net Framework 4.5</strong> hedefli düşünüp, <strong>async</strong> ve <strong>await</strong> anahtar kelimelerini devreye sokabilirsiniz.</li>
<li><strong>Excel</strong>’ de yapılacak olan değişikliklerin, <strong>Save</strong> işlemleri sonrasında veri kaynağına doğru yansıtılmasını düşünebilirsiniz.</li>
<li>Bazı <strong>View</strong>’ lardan yararlanarak <strong>Sheet</strong> içerisine çok basit anlamda <strong>Chart</strong><em>(örneğin bir Pie Chart çok şık durabilir)</em> çizdirmeyi deneyebilirsiniz</li>
</ul>
<p>vb <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_193.png" alt="Winking smile" /> Burada hayal gücünüzü kullanmadan önce, bir <strong>Excel</strong> uygulamasının aslında bir <strong>Windows</strong> uygulaması olduğunu ve <strong>Visual Studio 2012</strong> tarafında istenildiği gibi özelleştirilebildiğini düşünmenizde yarar olacaktır. Nitekim gördüğünüz üzere aynen bir<strong> Windows Forms</strong> uygulamasında olduğu gibi olay metodlarına girebiliyor ve <strong>C#</strong> kodlarımızı konuşturabiliyoruz. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://buraksenyurt.com/pics/2013%2f3%2fHowTo_ExcelWithEF.zip">HowTo_ExcelWithEF.zip (1,20 mb)</a></p>
<p><span style="color: #ff0000;">[Orjinal Yazım Tarihi 03-05-2013]</span></p>2013-06-30T17:57:00+00:00entity frameworkexceloffice interopoffice developmentvisual studio 2012cellsbsenyurtÖzellikle Sheet’ ler veya Workbook’ lar kodlanabilir birer C#(Vb.Net) dosyası olduğu için, uygulama bazında istediğimiz taklayı atma şansına sahibiz. İşte bu düşünceler ışığında yola çıktığımız ve okumakta olduğunuz yazımızda, Excel’ i, Entity Framework’ ü, C#’ ı işin içerisine katacak ve birbirleri ile konuşmalarını sağlamaya çalışacağız. Haydi hiç vakit kaybetmeden yola koyulalım. Ama önce örnek senaryomuz...https://buraksenyurt.com/pingback.axdhttps://buraksenyurt.com/post.aspx?id=86309b12-3593-4895-b0d7-9820a4ee39dc4https://buraksenyurt.com/trackback.axd?id=86309b12-3593-4895-b0d7-9820a4ee39dchttps://buraksenyurt.com/post/Excel-ve-Entity-Framework-Konusuyor#commenthttps://buraksenyurt.com/syndication.axd?post=86309b12-3593-4895-b0d7-9820a4ee39dc