Elektroda.pl
Elektroda.pl
X

Search our partners

Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[C#] Eksport do pliku doc

Defice 11 Feb 2012 12:36 4279 18
  • #1
    Defice
    Level 25  
    Witam, potrzebuje napisać program, który będzie czymś na kształt modułu zamówień. Programik ma być prosty tzn. wprowadzane będą do niego dane za pomocą jednego tylko formularza. Zrobiłem już coś takiego jako bazę Access, ale niestety nie może być (odbiorca twierdzi, że to zbyt zawiłe). Generowanie raportu -> zapisanie pliku -> wchodzenie na e-mail -> dodanie załącznika -> wysłanie e-mail



    Przechodząc do konkretów:
    Do programu wprowadzam takie wartości jak: wysokość i szerokość (są to wymiary płyty wiórowej) oraz informacje o tym które z krawędzi mają zostać oklejone okleiną. Aplikacja nie będzie się rozrastać jest trywialna. Wynikiem ma być tabela, którą w Accessie realizowałem za pomocą prostego raportu z tabeli z dodaną stopką z danymi zamawiającego (zamawiający jest tylko 1, podobnie jak odbiorca).

    Pytanie brzmi następująco: czy da się stworzyć aplikacje która będzie eksportować to od razu do pliku doc ? (tylko w takim formacie dane są odbierane przez wykonawce). Aplikacje muszę tak zrobić, że wysyłanie będzie realizowane przez 1 button.

    Wysyłanie odbywać się będzie za pomocą metod przedstawionych Tutaj
  • #2
    marcinj12
    Level 40  
    Współczuję "rozgarniętego inaczej" klienta ale cóż, takie uroki tej pracy... :)
    To co chcesz zrobić na pewno jest wykonalne, pytanie jakim nakładem pracy i dodatkowych ograniczeń?
    Myślę że w Accessie też by można to zrobić - stworzyć formularz z jednym przyciskiem i w nim umieścić makra automatycznie generujące przygotowany raport, zapisujące plik, nie wiem jak z wysyłaniem załącznika, ale gdyby zamiast DOC mógł to być PDF, to przykładowo PDF Creator ma taką opcję że automatycznie tworzy załącznik i otwiera okienko domyślnego programu poczty (wydruk raportu na wybranej drukarce w Accesie na pewno można zrealizować).

    Ale wracając do C#: klasa MailMessage ma właściwość Attachements, którą możesz użyć do dodania załącznika, na stronie MSDN jest dobry przykład na to.

    Gorzej będzie z utworzeniem dokumentu DOC - ponownie, gdyby był to PDF to są darmowe i proste w obsłudze biblioteki do tego (np. iText lub iTextSharp). DOC to najgorszy możliwy wybór, gdyby mógł to być DOCX, to z racji częściowo otwartego formatu OpenXML są darmowe biblioteki do jego generowania, jak DocX.

    Dokument DOC nie ma otwartego formatu więc może być trudno znaleźć darmową bibliotekę do jego generowania. Zawsze można wykorzystać biblioteki COM Worda (Interop.Word), jednak wymagają one do pracy zainstalowanego Worda oraz są problematyczne przy zwalnianiu zasobów (przynajmniej Excel taki był, miałem kiedyś z nim przeboje...). Generalnie spróbuj coś w ten deseń: przykład, ewentualnie stwórz sobie templatkę dokumentu, zapisz w zasobach, a generując zamieniaj znaczniki na dane metodą Find And Replace: tutaj.

    Po połączeniu tego w całość coś powinno się dać z tego stworzyć...
  • #3
    Mad.
    Level 18  
    Póki nie ma żadnych postów, rzucę pierwszym pomysłem. Dysponując środowiskiem MS Visual Studio (2008 lub nowsze) i MS Office (2003 lub nowsze) możesz w prosty sposób tworzyć pliki Worda czy Excela. Nie jestem tylko pewny czy jest to możliwe w wersji Express. Wystarczy wykorzystać biblioteki Microsoft.Office.Core i Microsoft.Office.Interop.Word. Na MSDN są przedstawione tutoriale. Innych rozwiązań nie znam, bo akurat dysponowałem wyżej wymienionymi aplikacjami.
  • #4
    Defice
    Level 25  
    I to mi się podoba :) Jest konkret trzeba to jeszcze zrealizować :) Wielkie dzięki, wykorzystam rady, widać da się to zrobić, muszę jeszcze zadzwonić czy PDF im pasuje, jeśli uda się to wg. tego co mówi marcinj12 powinno być łatwiej, cóż szkoda że teraz nie mogę tego sprawdzić ale egzamin ważniejszy, jeszcze się odezwę, bo jak siebie znam będą jeszcze problemy.

    Korzystam z Visual Studio 2010 w pełnej wersji, więc biblioteki Microsoft.Office.Core i Microsoft.Office.Interop.Word też będzie można wykorzystać
  • #5
    truski
    Level 17  
    Jest jeszcze jedna opcja - jest w Javie biblioteka do obsługi dokumentów Office'a - Apache POI, natomiast tutaj jest informacja jak zrobić z niej wersję dla .Net. Jest to rozwiązanie, które będzie działać bez instalacji Office'a

    Druga opcja mniej hardcorowa to zainteresuj się korespondencją seryjną - programowa realizacja również odbywa się przez COM Interop services. Jednakże jak koledzy wspomnieli integracja z MS Office wymaga zainstalowanego MS Office, gdyż biblioteki dostępne w visual studio są tylko interfejsami programowymi do Office'a i go nie zastąpią, dlatego zanim zaczniesz implementację sprawdź czy klient posiada Office'a na komputerze.

    A co do eksportu do PDFa to mógłbyś spróbować zrobić to przez report viewer'a - Visual Studio posiada tę kontrolkę co sprowadzałoby się stworzenia szablonu RDL, który za pomocą kontrolki można eksportować do PDF i innych formatów. To rozwiązanie jest o tyle fajne, że szablon możesz zbudować i obsłużyć przy użyciu Visual Studio Express Edition.
  • #6
    marcinj12
    Level 40  
    To ja dodam jeszcze, że jeżeli klient zgodzi się zamiast DOC otrzymywać plik Excela .xls (w końcu ten sam pakiet, nie powinno mu robić różnicy...), to pakiet o którym Kolega wspominał dla .NET'a nazywa się NPOI (w dziale Downloads są czytelne przykłady w paczce Examples) - bardzo łatwo, zgrabnie, szybko i bez konieczności instalowania Excela tworzy pliki .xls którymi o wiele łatwiej zarządzać tworząc tabelę niż np. tworzyć ją w .doc'u. Piszą że NPIO obsługuje też tworzenia .doc, choć nigdy tego nie próbowałem, za to do .xls'a - jak najbardziej polecam.
  • #7
    Defice
    Level 25  
    Muszę coś pokombinować, mi też ten doc nie pasuje, w sumie xls będzie równie dobry a może nawet lepszy, jeśli nie to ten pdf trzeba będzie uskutecznić :)

    Dodano po 4 [godziny] 6 [minuty]:

    Generowanie stringów poszło bardzo szybko i o dziwo bezboleśnie. Problem natomiast mam z inną sprawą, a mianowicie z podglądem. Wprowadzanie to kilka textboxów i buttonów, jak najlepiej zorganizować podgląd zawartości w tym samym oknie (po prawej od textboxów) ? Bawiąc się z SQL robiłem to jednak nie wiem jak pod GridView podpiąć ten plik doc, ma ktoś jakieś pomysły ?

    Kod może mało przejrzysty, ale wystarczający

    Code: csharp
    Log in, to see the code
  • #8
    marcinj12
    Level 40  
    Defice wrote:
    Generowanie stringów poszło bardzo szybko i o dziwo bezboleśnie.
    Proszę, niech Kolega powie że sobie z nas jaja robi tym kodem do zapisu "doc'a"... Albo że w akcie desperacji postanowił z pełną premedytacją oszukać niezbyt rozgarniętego klienta licząc, że klient się nie połapie (przynajmniej do pierwszego zapisu...), bo skoro dokument z rozszerzeniem .doc ma ikonkę Worda, to widocznie jest to doc.
  • #9
    Defice
    Level 25  
    Moment, bo nie rozumiem o co chodzi ? Moim celem było generowanie pliku z wymiarami tak, aby był on czytelny po otwarciu przez "panią w biurze". Nie potrzebuje nic więcej niż to aby plik miał rozszerzenie doc (inne są z automatu odrzucane)
  • #10
    marcinj12
    Level 40  
    Ano o to chodzi, że to jest zwykły plik tekstowy. Równie dobrze mógłby mieć rozszerzenie .txt i być otwierany w notatniku... Z "prawdziwym" doc'em nie ma to absolutnie nic wspólnego... Nie zrobisz w tym żadnej tabeli, żadnej stopki o których pisałeś - chyba że "starą metodą" ze znaków ASCII, ba, nawet tekstu nie pogrubisz...
  • #11
    Defice
    Level 25  
    No tak, tu się zgodzę. Ale nie traktuj tego aż tak poważnie, pisałem że to mała trywialna aplikacja. Nawet nie będą przechowywane generowane przez nią pliki. Jeśli Cię zwiodłem to przepraszam, chodziło mi w sumie o dokładnie to co jest teraz, bałem się tylko, że takie "stworzenie doca" nie zadziała. A co do stopki, to w ten sposób wyraziłem to, że po podaniu pożądanych przeze mnie wartości na końcu dokumentu zostanie wygenerowany tenże ciąg.

    stopa = "\n\n\nKolor: "+okleina+"\nZamawiajacy: xxx\ntel. yyy\nzzz";

    Trochę chyba jeszcze za cienki jestem na zrobienie czysto krwistego doc'a z tabelkami itp. Patrząc na to z drugiej strony nie jest mi to potrzebne, a nakład pracy jaki na to pójdzie nie zostanie doceniony przez nikogo.

    Reasumując: Może źle sprecyzowałem mówiąc o doc'u, chodziło bardziej o dowolny plik tekstowy posiadający takie rozszerzenie (niestety wymóg arcy konieczny...).

    Sądzę, że klient nie poczuje się poszkodowany otrzymując tak wyglądającą aplikacje, jestem pewien że będzie nawet zadowolony (biorąc pod uwagę, że to praca niemal charytatywna, w szczegóły nie wchodząc). Teraz pozostaje jedynie skończyć mi button odpowiedzialny za wysłanie e-maila i tyle, nawet nad wyglądem nie mam zamiaru pracować.
  • Helpful post
    #12
    marcinj12
    Level 40  
    Defice wrote:
    Jeśli Cię zwiodłem to przepraszam
    Nie, no mnie nie zawiodłeś ;) Po prostu wszystkie odpowiedzi które dostawałeś były ukierunkowane na - wcale nie takie proste - utworzenie "prawdziwego" doc'a obsługującego formatowanie etc. Gdybyś na początku wspomniał że chodzi o zwykły TXT, szybciej byś uzyskał potrzebne informacje :)
    pozdrawiam
  • #13
    Defice
    Level 25  
    Potrzebuje jeszcze jedną rzecz, a mianowicie progressbar podczas wysyłania. Problem polega na tym jak zrobić by dopełnił się on w momencie gdy wiadomość się wyśle ? Co prawda ten moment widać (po zmianie koloru przycisku), wolałbym progressbar tylko nie wiem jak dziada skonfigurować System.Threading.Thread.Sleep(500) i progressBar1.Increment(100) wstawiłem po operacji send, ale nie działa to :/ Wychodzi na to, że to zamraża operacje wysyłania (tak mi się wydaje)?
  • #14
    webmortiz
    Level 20  
    Do obsługi progressBar najlepiej użyć backgroundWorker (wizualny komponent upraszczający obsługę wątków) i w skorzystać w nim z eventów DoWork, ProgressChanged oraz WorkCompleted (czy jakoś tak). Przykładów w necie jest sporo więc myślę że znajdziesz interesujące Cię praktyczne rozwiązanie, chociażby od razu zorientowane pod progressBar.
  • #15
    Mad.
    Level 18  
    Rozumiem, że chciałbyś aby program był "dostępny" dla użytkownika w czasie wysyłania maila, oraz żeby po wysłaniu maila poinformować o tym użytkownika. Jeżeli działasz w jednym wątku to nie jest to możliwe. System.Threading.Thread.Sleep(500) zamrozi Ci wątek na 500 ms i nic nie będziesz mógł zrobić przez ten czas. Poza tym nie wiesz jak długo potrwa wysyłanie maila. Rozwiązania są dwa:
    a) osobny wątek:
    - z kodu,
    - za pomocą gotowej kontrolki backgroundWorker jak napisał webmortiz - wydaje mi się, że dla Ciebie najprostsze; w DoWork wysyłasz maila, a w RunWorkerCompleted ustawisz progress bar,
    b) wykorzystując asynchroniczną naturę delegata - według mnie najprostsza metoda jeśli zna się składnię C#. Asynchroniczne wywołanie właśnie nadaje się do takich prostych rzeczy. Jeśli chcesz, mogę napisać krótki przykład.

    Poza tym na pewno napotkasz na kolejny "problem". Jeżeli kontrolka ma być zmodyfikowana w innym wątku, niż w tym w którym powstała musisz użyć odpowiedniego wywołania. Szczegóły tutaj: https://www.elektroda.pl/rtvforum/topic2009707.html
  • #16
    Defice
    Level 25  
    Mad. wrote:
    Rozumiem, że chciałbyś aby program był "dostępny" dla użytkownika w czasie wysyłania maila


    Nie, wysłanie maila to ostatnia rzecz jaką użytkownik będzie robić przez zakończeniem pracy z aplikacja, chodzi tylko o odzwierciedlenie czasu wysyłania przy pomocy progress bara, tak aby użytkownik widział, że wiadomość została już wysłana i może wyłączyć aplikacje
  • #17
    Mad.
    Level 18  
    Dziwne rozwiązanie z Twojej strony, ale jeśli odpowiada Ci zawieszenie się okna na czas wysyłania maila to ok. Jeśli chcesz po prostu pokazać, że mail jest wysyłany to możesz użyć tego (zresztą i tak zostanie zawieszone podczas wysyłania maila, wiec trochę bez sensu...):

    Code: csharp
    Log in, to see the code

    Następnie wysyłasz maila, a po wysłaniu, ustawiasz progressbar na 100%:

    Code: csharp
    Log in, to see the code

    Jeżeli chcesz ustawiać postęp progressbaru według rzeczywistych wysłanych danych to będziesz to musiał zrobić w osobnym wątku.

    Osobiście radziłabym Tobie nie zawieszać okna i użyć wielowątkowości, jak opisałem to w poprzednim moim poście.
  • #18
    webmortiz
    Level 20  
    W przypadku wysyłania maila nie jesteś w stanie procentowo dla progressbara okreslić ile czasu to zajmie, nawet w sekundach czy minutach. ProgressBar w takim wypadku powinien działać jako marque czy jakoś tak - nie procentowo a falująco - w ten sposób pokazuje że "coś" się dzieje a nie ile jeszcze zostało. Co do backgrounWorkera - blokujesz wyłączenie aplikacji na czas wysyłania maila i w bgWorkerze odpalasz progressa. Tak jak pisał Mad. będziesz miał za pewne problem z uzyskaniem dostępu do kontrolki progress Bara z wątku głównego w wątku bgW. Znam na to 2 rozwiązania - przekazywanie danych pomiędzy wątkami delegatami albo ustawienie w konstruktorze the CheckForIllegalCrossThreadCalls na false - w przypadku progressBara się sprawdzi i można się do niego dostać bez względu na wątek ale mimo iż jest to najprostsze rozwiązanie uważałbym z nim.
  • #19
    Defice
    Level 25  
    Problem rozwiązałem w inny sposób, puki co program po wysłaniu wyłącza się sam, chociaż progress barowi i tak nie odpuszcze, ale sesja ma teraz wyższy priorytet :/

    Dziękuje za wszystkie wypowiedzi, temat uważam za zamknięty.