Und die Antwort auf Deine 2. Frage:
Ich weiss ja nicht was Du mit deiner Excel-Referenz book noch alles tun möchtest, bzw. tust, aber wenn Du den Zugriff auf Excel nicht mehr benötigst solltest Du natürlich Excel anschliessend wieder schließen, um einen sauberen Zustand im Programm zu haben.
Ich habe mir ein kleines Programm geschrieben, das die Version in der AssemblyInfo.cs nach jedem Build als Release-Version hochsetzt.
Funktioniert für meine Zwecke hervorragend
Und so wie ich das verstanden habe, möchte er eben nur das Usersteuerelement "schliessen".
Aber ich denke, die Diskussion darüber ist wohl illusorisch 😃
Er spricht aber vom Close()-Befehl.
Und so wie er es beschreibt, möchte er wohl Usercontrols damit schließen.
Also, so wie ich das sehe, sprechen wir über Usercontrols, die im Hauptfenster geöffnet werden. Also keine eigenen Fenster.
Wenn dies der Fall ist, dann dürfte der Close()-Befehl hier falsch sein, denn der schließt ja die Form.
Also entweder statt der Usersteuerelemente Fenster (Forms) erstellen, und die dann wieder mit Close() schließen, oder wenn Dir das nicht möglich ist, die Usersteurelemente direkt auf die Form ziehen (und nicht jedesmal neu erzeugen) und dann nur immer sichtbar und unsichtbar machen.
Das liegt daran, daß Jet-Engine als Programm im Hintergrund arbeitet, und die Daten oft nicht sofort in die Datenbank schreibt.
Erst nach einer gewissen Zeit (keine Ahnung wann), spätestens nach Programm-Ende und dem Schliessen der DB wird das Ganze dann körperlich geschrieben.
Deswegen findest du erst viel später, bzw. nach Programm-Ende und Neustart die Daten erst wiedere in Access.
Es gibt da zwei Möglichkeiten:
Du packst den Speichervorgang in eine Transaction mit anschliessenden Commit. (da schreibt die Engine die Daten sofort)
oder, wenn nichts dagegen spricht nimmst Du eine richtige SQL-Datenbank wie z.B. SQLServer, SQLite usw.
Das Zauberwort, das Du hier suchst ist Latebinding.
Stelle Dein Anbinden von Office darauf um und dann sollte eigentlich jede Office Version damit arbeiten.
NetOffice arbeitet übrigens auch mit Latebinding.
Ich habe die Dotnetpro schon aboniert, seit es sie gibt.
Für mich ist sie ganz interessant.
Aber rechne doch mal aus:
150,-- € für 1 Jahre = 12 Fachzeitschriften incl. DVD!
Das sind 12,50 @ pro Monat/Zeitschrift.
Das sollte eigentlich kein Problem sein. - Trink halt ein paar Biere weniger im Monat 😁
Wenn Du kein Abo möchtest, dann kannst Du dir die Zeitschrift sicher auch in jedem gut sortiertem Bücherladen kaufen oder bestellen.
da muß man eben entscheiden was sinnvoller ist:
oder
Irgendwann geht das jemanden doch so auf die Nerven, daß dann doch entsprechend Geld fliesst.
Du kannst Dir aber auch eigene Steuerelement bauen und die von dem original Steuerelement ableiten. Da kannst Du dir dann Deine Events selbst definieren.
wünschen kann man sich viel 😃
aber so geht das meines Wissens nach nicht.
Du mußt dann für jeden Typ Deinen eigenen Cast schreiben.
Entweder mit if - elseIf oder mit switch
Zum Beispiel:
foreach (DataRow row in dataset.Tables[sheetName].Rows)
{
var typ = row[comboBoxEAN.SelectedItem.ToString()].GetType()
.
.
.
string Ean = row.Field<string>(comboBoxEAN.SelectedItem.ToString());
}
ich vermute da mal, daß Deine Id , die Du in der Select-Abfrage als String definiert hast in Deiner Exceltabelle als Zahl definiert ist.
D.h. Der Typ String und der Typ Zahl passen nicht zueinander.
Da reicht es auch schon, wenn in Excel auch nur eine Zeile falsch formatiert wurde, um diesen Fehler zu erzeugen:
Lösung: In diesem Fall die komplette ID-Spalte in Excel als String formatieren.
Also als erstes:
Das was Du als ConnectionString bezeichnest ist kein ConnectionString sondern dein CommandString.
Der ConnectionString ist ein String, der die Connection zur Datenbank öffnet.
Der CommandString den Du hier meinst, ist ein String der eine Anweisung an die Datenbank beinhaltet. Also Etwas was die Datenbank tun soll.
In Deinem Fall eine Select-Anweisung.
Google wird Dir hier bei der Suche nach ConnectionString natürlich etwas anderes bringen.
Deine Fehlermeldung bedeutet hier, daß ein Feld, das Du in dieser Select-Anweisung benutzt (hier Vorname, Nachname, Id) nicht in der Datenbank vorkommt.
Bei
C#-Code:
DataRow[] rows = base_db.Ausgaben.Select("Jahr([Datum]) = " + jahr + " UND Monat([Datum]) = " + monat);
bringt er eine"System.Data.EvaluateException" da er Jahr() nicht kennt.
Probier das mal mit Year(Datum) und Month(Datum)
Der Kern von Access spricht englisch. Das ist wie bei jeder anderen SQL-Datenbank.
Bei meinem o.g. Versuch bringt die Entwicklungsumgebung
Fehlermeldung:
Ein Ausnahmefehler des Typs "System.FormatException" ist in mscorlib.dll aufgetreten.
Zusätzliche Informationen: Die Zeichenfolge wurde nicht als gültiges DateTime erkannt.
Zwischen den #-Zeichen muß ein komplettes Datum stehen. Hier fehlt doch der Tag. Monat und Jahr ist eben kein gültiges Datum.
@T-Virus
Bei Office ist schon immer das Problem, daß die Arrays nicht 0-basiert, sondern 1-basiert sind. Die Entwickler von Office kannten wohl eine 0 😃.
Wenn Du die Access-"Datenbank" nur als Datenbank verwendest, als ohne irgendwelches Oberflächen-Gefrickel, dann benötigst Du auf dem Computer, auf dem Dein Programm dann läuft, gar kein Access (auch keine Runtime).
Das hat Microsoft schon so aufgebaut.
Du benötigst anb Windows 7 einfach nur den Microsoft.ACE.OLEDB.12.0-Provider. Den kannst Du bei MS kostenlos runterladen.
Bei Windows XP wäre das allerdings noch der Microsoft.Jet.OleDB.4.0
Aber ansonsten gebe ich meinen Kollegen Recht: Access solltest Du hier möglichst nicht mehr verwenden.
@Herbivore,
stimmt, du hast recht. - wieder was dazugelernt
Au mußt natürlich vorher die Anzahl der Zeilen ermitteln, da Du ja die Höhe des Rectangles ermitteln mußt.
D.h. Du mußt einfach für jede Zeile im Array berechnen, auf wieviele Zeilen sie bei einer vorgegebenen Textbreite umbrechen würde. Ist zwar ein bisschen aufwändig, aber geht.
z.B. vom String solange von rechts her Wörter entfernen, bis die ermittelte Textbreite kleiner oder gleich der vorgegebenen Breite ist.
Dann dort einen Zeilenumbruch einbauen.
Den restlichen String immer weiter genauso behandeln, bis nichts mehr übrig ist.
Du hast das schon richtig gelesen.
Du mußt bei Verwendung von den Bordmitteln von C# tatsächlich alles selbst berechnen und positionieren. Auch Zeilenwechsel.
siehe auch:
suche kostenlose report engine für c#
Es gibt einige kostenpflichtige Module die solche Arbeiten für Dich erledigen wie z.B.
crystal Reports
List&Label
DevExpress
Einiges Interessantes findes Du auch unter
http://www.codeproject.com/KB/printing/
Wenn Du vorwiegend mit Text arbeitest wäre evtl. auch das interessant:
http://www.textcontrol.com/en_US/
Das gibts als Freeware in einer Lite-Version, und auch als Kaufversion.
Mal etwas logisch denken!
inflames2k hat doch schon gesagt, woran es liegt.
Die Fehlermeldung sagt doch auch alles.
Du setzt die DataSource im Konstructor des Controls.
Wenn Du dann das Control auf ein Form ziehst, wird eben zuerst die Datasource zugewiesen.
Dann kommt logischweise der Fehler, wenn danach Items.AddRange ausgeführt wird.
Du mußt einfach die DataSource woanders setzen.
ich würde einfach mal die Festplatte nach dem Dateinamen des Add-Ins durchsuchen lassen. Wenn es vom Outlook noch ausgeführt wird, müsste es ja noch irgendwo körperlich vorhanden sein.
Außerdem kannst Du ja auch mal die gesamte Registry danach durchsuchen lassen. Vielleicht steht ja doch noch was irgendwo drin.
Wenn ein User an Sachen rumfummelt, die ihn nichts angehen, dann muß er auch die Konsequenzen tragen. Am Besten lernt er es, wenn die Reperatur dann Geld kostet.
Du kannst bei Split auch ein Array mit verschiedenen Trennzeichen übergeben.
Schau in der Dokumentation nach.
mist, war zu langsam 😃
Beim Anlegen eines neuen Sheets stehen alle Formatierungen der Zellen auf Standard. D.h. Excel versucht anhand der Daten, die dann reingeschrieben werden, den Typ zu erkennen.
Dieser Typ wird manmal von Excel her falsch interprtiert. Deswegen passiert of so etwas.
Du mußt einfach die Zelle vor dem reinschreiben als Datum formatieren.
Dann kapiert es auch Excel.
Dann hast Du möglichweise ein Problem in Deiner Windows-Installation.
Vermutlich blockiert dann ein Gerät, das Du am USB hängen hast deinen Zugriff auf Deine Festplatten. VS will dann wohl so lange warten, bis wieder Daten von der Platte kommen.
Durch das Entfernen des USB-Gerätes wird dann der Plattenzugriff wieder freigegeben, aber VS dann wohl intern schon abgebrochen.
Versuche doch einfach mal zu arbeiten, wenn kein USB-Gerät angeschlossen ist.
Dann müßte das Debugen eigentlich funktionieren.
Wenn das so ist müßtest Du durch probieren einfach mal feststellen welches Gerät den Fehler verursacht. Wenn das eine Festplatte oder USB-Stick ist, dann das Ding mal komplett neu formatieren.
Wenn es dann nicht klappt, dann fällt mir eigentlich nur noch ein, das komplette SYstem platt zu machen und neu hochzuziehen.
Ich vermute jetzt mal, daß sich Dein Quelltext auf einem USB-Laufwerk befindet.
VS hat manchmal Probleme mit USB. Manchmal werden da auch eingebundene Projekte und Verweise nicht mehr gefunden.
Ich habe meine Projekte prinzipiell immer auf einer eingebauten Festplatte.
Da habe ich keine Problem.
Also ich mache das in der Regel so, daß ich bei Festpreis/Pauschalangeboten keinen Weitervertrieb der von mir erstellten Software zulasse. Hier trage ich ja das finanzielle Risiko (kann ja sein, daß ich mich verkalkuliert habe).
Bei einem Weitervertrieb mache ich das nur auf Stundenbasis. Den eventuellen Gewinn streicht ja dann auch nur mein Kunde ein. Dann muß er auch das finanzielle Risiko tragen. Was er dann mit der Software macht ist seine Sache.
Ich habe allerdings momentan auch ein Programm in Arbeit, bei dem ich eine Partnerschaft eingegangen bin. Ich mache das Programm und mein Partner, der auch die Idee hatte, macht den Vertrieb. Der Gewinn wird geteilt.
durch das acht-stündige Programmieren pro Tag kommt man da leicht durcheinander
wenn Du "nur" 8 Stunden progranmmierst ist das schon klar. 😃
Aber Spaß beiseite, da hilft dann nur eins: Das Problem erst mal auf Eis legen, eine Nacht darüber schlafen, und am nächsten Tag weitermachen, dann kommt man schon auf eine entsprechende Lösung.
Bei mir hilft das immer 😃
Suche halt erst den Hauptordner und suche dann im Hauptorder alle weiteren Ordner, dann bekommst Du auch nur alles was im Hauptordner ist
und genau an den 90 tabellen liegt Dein Knackpunkt.
So wie Diräkt schon geschrieben hat, solltest Du keine 1:1-Beziehungen aufbauen.
Adressdaten und Kommunikationsdaten sind pro Person nur einmal vorhanden, und gehören daher in die Personentabelle.
Wenn Du das mit allen solchenTabellen machst, dann hast Du am Schluß keine 90 Tabellen sondern bedeutend weniger.
Ich müsste jede Detailtabelle nach Einträgen zu der Person durchsuchen und die entsprechenden Daten zum Baum hinzufügen. Das ist erstens nicht performant und zweitens schlecht wartbar.
Mußt Du nicht, denn mit einer entsprechenden SQL-Anweisung gibt Dir Deine Datenbank nämlich dann schnell alle benötigten Daten zurück.
ich denke, da müßte man etwas mehr Code sehen!!!
Mal eine ganz dumme Frage:
kann es sein, daß in Datenbank nach "RUTH" noch Leerzeichen, oder evtl. nicht druckbare Zeichen stehen?
Dann würde die Query natürlich nie p.Vorname == "RUTH" finden.
Mach doch mal p.Vorname.Trim(). Das entfernt alle führenden und nachfolgenden Leerzeichen
erst einmal unter "Gesendete Mails" nachprüfen, ob die mail tatsächlich zu dem Zeitpunkt rausgeschickt wurde.
Zeitpunkt vom Drücken des Buttons "Senden" ist nicht gleich dem tatsächlichen Zeitpunkts des Sendens. wenn der User z.B. gleich nach dem Drücken des Buttons Outlook beendet hat, dann ist die Mail u.U. noch gar nicht ráus.
Wenn der "echte" Sendezeitpunkt tatsächlich am Mittwoch war, würde hier den Grund bei dem Email-Provider vermuten, denn ab dem Punkt hast Du keine Kontrolle mehr über die Mail.
Alternativ könntest Du natürlich auch Deine Checkbox Teilen in die Checkbox ohne Text und ein extra Label mit dem Text für die Checkbox. Du hast dann eben nur 2 Controls zum Dis-/Enablen statt nur eins.
Access im Multiuserbetrieb ist immer ein Risiko.
Access ist dafür nicht ausgelegt.
Daß das bei Dir ein paar Jahre ohne Probleme lief ist purer Zufall.
Nimm den SQL-Server Express, wie schon BerndFfm geschrieben hat, und diese Probleme sind weg.
Wenn Du die Datenbank dann noch auf einen Server oder ainen PC legst, an den niemand arbeitet, hast Du da mit Sicherheit auch noch einen Performance-Schub.
@Yankyy02
Dein Link verweist auf eine Access Runtime. Die ist nur dafür da, um Access-Programme auszuführen, ohne dass das komplette Access (mit Lizenz) auf dem Rechner installiert ist. Das hat mit einem Provider überhaupt nichts zu tun.
er muß halt den Microsoft.ACE.OLEDB.12.0 Provider installieren und das wars dann schon.
Stimmt, Textfelder in Access können nur maximal 255 Zeichen groß sein.
Wenn Du in Access größere Textfelder benötigst, dann mußt Du Memo-Felder verwenden
cmd.CommandText = "SELECT * FROM round WHERE TournamentID=" + listBox1.SelectedItem.ToString();
müsste in Deinem Fall
cmd.CommandText = "SELECT * FROM round WHERE TournamentID='" + listBox1.SelectedItem.ToString() + "'";
heissen. Ein String muß in einer SQL-Anweisung in Hochkomma eingeschlossen werden
Das Problem liegt hier bei Access
Der Provider, oder auch Access selbst puffert die gespeicherten Datensätze erst mal zwischen.
D.h. wenn über ein Programm neue Daten nach Access geschickt werden, und sofort anschließend diese Daten wieder abgefragt werden, stehen die noch gar nicht in der entsprechenden Tabelle.
Das kann man auch überprüfen, indem man nach dem Speichern der Daten direkt in Access die Tabelle öffnet. Da steht dann meistens auch noch nichts drin.
Die Lösung ist, hier die Datenspeicherung (auch wenn es sich evtl. auch nur um einen Wert handelt), in eine Transaktion zu packen. Damit wird Access gezwungen, die Daten ohne Zwischenpufferung direkt in die Tabelle zu schreiben.
Dann funktioniert es auch immer.
Also ich mache das folgendermaßen:
Fast alle meine Steuerelemente, die ich verwende sind abgeleitete Steurelemente mit Erweiterungen. Dadurch sind es eigene Klassen.
Über AOP mit PostSharp lasse ich Starten und Beenden jeder Methode mit den Methoden-Parametern über Log4Net mitprotokollieren. Bei einem Fehler wird die Fehlermeldung mit dem gesamten Stacktrace ebenfalls protokolliert.
Anschliessend wird die Protokolldatei sowie eine Hardcopy der aktuellen Bildschirmmaske per Mail an mich geschickt.
Ich weiss dann meistens schon alles Nötige, bevor die Rückmeldung des Users kommt.
Ammer in Deiner selbstgeschriebenen Show Methode vor dem eigenlichen base.Show. Wenn die Überprüfung fehl schlägt, kannst Du das dann entsprechen behandeln, bovor es weitergeht.
Ich habe solche Anforderungen auch öfters, und habe mir da ganz einfach geholfen.
Du mußt doch sowieso die Show oder Showdialog Methode aufrufen, um die Form anzuzeigen.
Überschreibe doch einfach die entsprechende Methode durch eine eigene. Da kannst Du dann alle Initialisierungsfunktionen ausführen.
Du darfst dann nur nicht vergessen, am ende Deiner Methode die entsprechne Base-Methode aufzurufen
DGV ableiten und die benötigte Funktion selbst entwickeln.
Ich habe mir so alle Steuerelemente, die ich benötige an meine Bedürfnisse angepasst.
Ich hatte mal das gleiche Problem.
Ich habe dann einfach vor jeden Befehl in der Main-Methode ein Messagebox geschaltet, die mir einfach den Befehl angezeigt hat. Da siehst Du dann nämlich genau, in welcher Zeile das Programm aussteigt.
Da kommt dann bestimmt die große Glübirne 😃
versuchs mal mit http://netoffice.codeplex.com/
Außerdem solltest Du wie manfred.baur schon geschrieben hat, Excel sichtbar machen, und dann einmal schrittweise debugen. Dann siehst Du nämlich genau, was im Excel vor sich geht.
Stimmt, bei den Tab-Pages gibt es kein Enable und auch kein Visible.
Ich hatte das selbe Problem, und ich habe das so gelöst, daß ich das Tab-Control und TabPage abgeleitet habe, und mir mein eigenes Property Visible gebaut habe.
Ganz einfach bei Visible= false die TabPage in ein Objekt gespeichert, und dann mit Remove entfernt. Wenn ich das anschließend wieder auf Visible=true gesetzt habe, wird es einfach aus dem Objekt wieder mit Add zum TabControl hinzugefügt, und es funktioniert wieder ganz normal.
Wenn es hier bei einem Arbeitsblatz immer ausgeblendet sein soll, muß man es ja nicht einmal zwischenspeichern.
Vielleicht ein Verständnisproblem mit dem Recordset.
Ein Recordset besteht aus n Records, wobei die Anzahl n sich mit der Eigenschaft RecordCount des Recordsets ermitteln läßt. RecordCount ist aöso nicht die Anzahl der Daten in den Feldern.
Ein Records besteht aus m Feldern (Fields).
Du kannst das mit einem zweidimensionalen Array vergleichen, oder besser erklärt:
Stelle Dir ein Excelsheet vor. Das wäre ein Recordset.
Jede Zeile des Excelsheets ist ein Record.
Jede Spalte eines Excelsheets ist ein Field im Recordset.
Ich denke damit solltest Du eigentlich zurecht kommen.
Das Zauberwort heisst Debuggen.
Dann siehst Du doch selbst was passiert, bzw. nicht passiert